AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/10/15 04:32 flow patch-triage
5m Args:
null

Results:
{
  "EnableConfigs": [
    "CAN",
    "CAN_RAW",
    "CAN_BCM",
    "CAN_ISOTP",
    "CAN_GW",
    "CAN_DEV",
    "CAN_VCAN",
    "CAN_KVASER_USB",
    "PROC_FS"
  ],
  "FocusSymbols": [
    "bcm_release",
    "raw_release",
    "isotp_release",
    "isotp_rcv",
    "isotp_bind",
    "bcm_rx_setup",
    "raw_enable_filters",
    "can_rx_register",
    "can_rx_unregister",
    "can_send",
    "can_rcv",
    "canfd_rcv",
    "canxl_rcv",
    "can_dropped_invalid_skb",
    "can_put_echo_skb",
    "cgw_create_job",
    "kvaser_usb_hydra_read_bulk_callback"
  ],
  "KMSANReasoning": "The patch series focuses on the Linux CAN subsystem and includes:\n1. Procfs formatting updates in net/can (replacing pointer formatting %pK with socket inode numbers and %ps symbol lookups, plus introducing can_reset_pkg_stats() to explicitly zero all fields of struct can_pkg_stats).\n2. Socket lifecycle and locking refactoring in BCM, Raw, and ISO-TP sockets (reordering RTNL vs notifier spinlock acquisitions to prevent deadlocks and race conditions).\n3. Packet bounds and length validation in drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c to ensure incoming USB command frames have sufficient bytes before parsing.\n4. Driver maintenance such as PM ops modernization (DEFINE_SIMPLE_DEV_PM_OPS), safe SKB freeing (dev_kfree_skb_any), reference count fixes (of_node_put, clk_put), and removal of the deprecated softing driver.\n5. In cc770_platform.c, fixing a logic bug where priv-\u003ecpu_interface was read before being assigned from platform data.\n\nNone of the changes introduce uninitialized stack or heap memory reads, struct padding leaks, or uninitialized kernel-to-user copy operations. The potential risks associated with these patches (deadlocks, use-after-free, out-of-bounds accesses) are already covered by LOCKDEP and standard KASAN. Therefore, a dedicated KMSAN session is not warranted.",
  "NeedsKMSAN": false,
  "Reasoning": "The patch series introduces significant changes and refactorings across the CAN core networking subsystem (net/can/) and CAN device drivers:\n1. Socket release \u0026 notifier concurrency refactoring: In bcm_release(), isotp_release(), and raw_release(), socket locking and notifier list removal were overhauled to serialize under RTNL, removing busy-wait loops and adding new WARN_ON_ONCE() runtime assertions to verify that notifiers are not concurrently executing on the socket being destroyed.\n2. Device validation: Checks for CAN device capability and mid-layer priv (can_get_ml_priv(dev)) replace ARPHRD_CAN checks across af_can, bcm, raw, isotp, and gw.\n3. Protocol and SKB handling: Added CAN-XL capability validation in can_dropped_invalid_skb(), updated frame content checking in isotp_rcv(), and improved bounds checking/skb freeing in can_put_echo_skb().\n4. USB driver packet parsing: In kvaser_usb_hydra, command size parsing and verification were overhauled to handle partial commands and validate command bounds.\n\nAll modified networking code is fully reachable in virtualized QEMU environments using standard CAN sockets (CAN_RAW, CAN_BCM, CAN_ISOTP), virtual netdevs (vcan), and USB fuzzing interfaces. Fuzzing is warranted to test the new locking invariants, assertions, and boundary checks.",
  "WorthFuzzing": true
}

1/1 2026/10/15 04:32 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit e266d8df68870dedf5e7f9fa0d4a7c435ea59542\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Oct 15 04:32:17 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml b/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml\nnew file mode 100644\nindex 0000000000000..d5cba5b1bac19\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml\n@@ -0,0 +1,65 @@\n+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)\n+%YAML 1.2\n+---\n+$id: http://devicetree.org/schemas/net/can/aeroflexgaisler,grcan.yaml#\n+$schema: http://devicetree.org/meta-schemas/core.yaml#\n+\n+title: Aeroflex Gaisler GRCAN and GRHCAN CAN controllers\n+\n+maintainers:\n+  - Marc Kleine-Budde \u003cmkl@pengutronix.de\u003e\n+\n+description: |\n+  The GRCAN and GRHCAN CAN controllers are available in the GRLIB VHDL IP\n+  core library.\n+\n+  On a LEON SPARC system there are no device tree source files. The nodes\n+  are built by the PROM from the AMBA plug\u0026play information, which does not\n+  provide a compatible string. The driver therefore matches on the node\n+  name, which is built as \"\u003ccore name\u003e@\u003cirq\u003e,\u003caddress\u003e\" from the \"name\" and\n+  \"reg\" properties of the AMBA plug\u0026play core.\n+\n+  The GRLIB build ID is not a property of the controller node either. It is\n+  read from the \"systemid\" property of the \"/ambapp0\" node, and the TX bug\n+  workaround is enabled when that property is absent or when its least\n+  significant 16 bits are smaller than 4100.\n+\n+select:\n+  properties:\n+    $nodename:\n+      pattern: '^(01_034|01_03d|GAISLER_GRCAN|GAISLER_GRHCAN)@'\n+  required:\n+    - $nodename\n+\n+properties:\n+  reg:\n+    maxItems: 1\n+\n+  freq:\n+    description:\n+      Frequency of the external oscillator clock in Hz, which is the\n+      frequency of the AMBA bus in the ordinary case.\n+    $ref: /schemas/types.yaml#/definitions/uint32\n+\n+  interrupts:\n+    maxItems: 1\n+    description:\n+      Interrupt number of the controller, as built from the AMBA plug\u0026play\n+      information.\n+\n+required:\n+  - reg\n+  - freq\n+  - interrupts\n+\n+additionalProperties: false\n+\n+examples:\n+  - |\n+    /* AMBA plug\u0026play children are named \"\u003ccore name\u003e@\u003cirq\u003e,\u003caddress\u003e\" */\n+    GAISLER_GRCAN@c,80000000 {\n+        reg = \u003c0x80000000 0x1000\u003e;\n+        freq = \u003c40000000\u003e;\n+        interrupts = \u003c12\u003e;\n+    };\n+...\ndiff --git a/Documentation/devicetree/bindings/net/can/grcan.txt b/Documentation/devicetree/bindings/net/can/grcan.txt\ndeleted file mode 100644\nindex 34ef3498f8870..0000000000000\n--- a/Documentation/devicetree/bindings/net/can/grcan.txt\n+++ /dev/null\n@@ -1,28 +0,0 @@\n-Aeroflex Gaisler GRCAN and GRHCAN CAN controllers.\n-\n-The GRCAN and CRHCAN CAN controllers are available in the GRLIB VHDL IP core\n-library.\n-\n-Note: These properties are built from the AMBA plug\u0026play in a Leon SPARC system\n-(the ordinary environment for GRCAN and GRHCAN). There are no dts files for\n-sparc.\n-\n-Required properties:\n-\n-- name : Should be \"GAISLER_GRCAN\", \"01_03d\", \"GAISLER_GRHCAN\" or \"01_034\"\n-\n-- reg : Address and length of the register set for the device\n-\n-- freq : Frequency of the external oscillator clock in Hz (the frequency of\n-\tthe amba bus in the ordinary case)\n-\n-- interrupts : Interrupt number for this device\n-\n-Optional properties:\n-\n-- systemid : If not present or if the value of the least significant 16 bits\n-\tof this 32-bit property is smaller than GRCAN_TXBUG_SAFE_GRLIB_VERSION\n-\ta bug workaround is activated.\n-\n-For further information look in the documentation for the GLIB IP core library:\n-http://www.gaisler.com/products/grlib/grip.pdf\ndiff --git a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml\nindex b9d9dd7a79676..4b94bc8d911be 100644\n--- a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml\n+++ b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml\n@@ -13,6 +13,8 @@ properties:\n   compatible:\n     oneOf:\n       - enum:\n+          - renesas,r9a08g045-canfd        # RZ/G3S\n+          - renesas,r9a08g046-canfd        # RZ/G3L\n           - renesas,r9a09g047-canfd        # RZ/G3E\n           - renesas,r9a09g077-canfd        # RZ/T2H\n \n@@ -132,7 +134,9 @@ properties:\n   power-domains:\n     maxItems: 1\n \n-  resets: true\n+  resets:\n+    minItems: 1\n+    maxItems: 2\n \n   reset-names:\n     items:\n@@ -185,8 +189,6 @@ required:\n   - clocks\n   - clock-names\n   - power-domains\n-  - assigned-clocks\n-  - assigned-clock-rates\n   - channel0\n   - channel1\n \n@@ -198,6 +200,7 @@ allOf:\n         compatible:\n           contains:\n             enum:\n+              - renesas,r9a08g045-canfd\n               - renesas,rzg2l-canfd\n     then:\n       properties:\n@@ -209,7 +212,6 @@ allOf:\n \n         resets:\n           minItems: 2\n-          maxItems: 2\n \n   - if:\n       properties:\n@@ -231,6 +233,8 @@ allOf:\n         resets:\n           maxItems: 1\n \n+        reset-names: false\n+\n   - if:\n       properties:\n         compatible:\n@@ -246,7 +250,6 @@ allOf:\n \n         resets:\n           minItems: 2\n-          maxItems: 2\n \n   - if:\n       properties:\n@@ -266,6 +269,7 @@ allOf:\n         compatible:\n           contains:\n             enum:\n+              - renesas,r9a08g045-canfd\n               - renesas,r9a09g077-canfd\n               - renesas,rcar-gen3-canfd\n               - renesas,rzg2l-canfd\n@@ -291,6 +295,25 @@ allOf:\n       patternProperties:\n         \"^channel[6-7]$\": false\n \n+  - if:\n+      properties:\n+        compatible:\n+          contains:\n+            const: renesas,r9a08g046-canfd\n+    then:\n+      properties:\n+        interrupts:\n+          minItems: 11\n+\n+        interrupt-names:\n+          minItems: 11\n+\n+        resets:\n+          minItems: 2\n+\n+      patternProperties:\n+        \"^channel[3-7]$\": false\n+\n   - if:\n       properties:\n         compatible:\n@@ -330,6 +353,7 @@ allOf:\n         compatible:\n           contains:\n             enum:\n+              - renesas,r9a08g045-canfd\n               - renesas,r9a09g047-canfd\n               - renesas,rzg2l-canfd\n     then:\n@@ -350,6 +374,22 @@ allOf:\n       properties:\n         reset-names: false\n \n+  - if:\n+      properties:\n+        compatible:\n+          contains:\n+            enum:\n+              - renesas,r9a08g045-canfd\n+              - renesas,r9a08g046-canfd\n+    then:\n+      properties:\n+        renesas,no-can-fd: false\n+        renesas,fd-only: false\n+    else:\n+      required:\n+        - assigned-clocks\n+        - assigned-clock-rates\n+\n unevaluatedProperties: false\n \n examples:\ndiff --git a/Documentation/networking/can.rst b/Documentation/networking/can.rst\nindex 536ff411da1d1..908c199cf6ada 100644\n--- a/Documentation/networking/can.rst\n+++ b/Documentation/networking/can.rst\n@@ -1040,17 +1040,17 @@ As described in :ref:`socketcan-receive-lists` the SocketCAN core uses several f\n lists to deliver received CAN frames to CAN protocol modules. These\n receive lists, their filters and the count of filter matches can be\n checked in the appropriate receive list. All entries contain the\n-device and a protocol module identifier::\n+CAN network device and the subscribed function name::\n \n     foo@bar:~$ cat /proc/net/can/rcvlist_all\n \n     receive list 'rx_all':\n-      (vcan3: no entry)\n-      (vcan2: no entry)\n-      (vcan1: no entry)\n-      device   can_id   can_mask  function  userdata   matches  ident\n-       vcan0     000    00000000  f88e6370  f6c6f400         0  raw\n       (any: no entry)\n+      device   can_id   can_mask   matches  sock_inode  function\n+       vcan0     000    00000000         0       63586  raw_rcv [can_raw]\n+      (vcan1: no entry)\n+      (vcan2: no entry)\n+      (vcan3: no entry)\n \n In this example an application requests any CAN traffic from vcan0::\n \ndiff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig\nindex a8fad6fe53020..fb16f67a99f99 100644\n--- a/drivers/net/can/Kconfig\n+++ b/drivers/net/can/Kconfig\n@@ -254,7 +254,6 @@ source \"drivers/net/can/peak_canfd/Kconfig\"\n source \"drivers/net/can/rcar/Kconfig\"\n source \"drivers/net/can/rockchip/Kconfig\"\n source \"drivers/net/can/sja1000/Kconfig\"\n-source \"drivers/net/can/softing/Kconfig\"\n source \"drivers/net/can/spi/Kconfig\"\n source \"drivers/net/can/usb/Kconfig\"\n \ndiff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile\nindex 4010d17f85836..fa2cdd7bcd0ac 100644\n--- a/drivers/net/can/Makefile\n+++ b/drivers/net/can/Makefile\n@@ -13,7 +13,6 @@ obj-y\t\t\t\t+= rcar/\n obj-y\t\t\t\t+= rockchip/\n obj-y\t\t\t\t+= spi/\n obj-y\t\t\t\t+= usb/\n-obj-y\t\t\t\t+= softing/\n \n obj-$(CONFIG_CAN_AT91)\t\t+= at91_can.o\n obj-$(CONFIG_CAN_BXCAN)\t\t+= bxcan.o\ndiff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c\nindex 4bddd015775bc..622c5d73e33a8 100644\n--- a/drivers/net/can/bxcan.c\n+++ b/drivers/net/can/bxcan.c\n@@ -1042,7 +1042,7 @@ static void bxcan_remove(struct platform_device *pdev)\n \tfree_candev(ndev);\n }\n \n-static int __maybe_unused bxcan_suspend(struct device *dev)\n+static int bxcan_suspend(struct device *dev)\n {\n \tstruct net_device *ndev = dev_get_drvdata(dev);\n \tstruct bxcan_priv *priv = netdev_priv(ndev);\n@@ -1059,7 +1059,7 @@ static int __maybe_unused bxcan_suspend(struct device *dev)\n \treturn 0;\n }\n \n-static int __maybe_unused bxcan_resume(struct device *dev)\n+static int bxcan_resume(struct device *dev)\n {\n \tstruct net_device *ndev = dev_get_drvdata(dev);\n \tstruct bxcan_priv *priv = netdev_priv(ndev);\n@@ -1076,7 +1076,7 @@ static int __maybe_unused bxcan_resume(struct device *dev)\n \treturn 0;\n }\n \n-static SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume);\n+static DEFINE_SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume);\n \n static const struct of_device_id bxcan_of_match[] = {\n \t{.compatible = \"st,stm32f4-bxcan\"},\n@@ -1087,7 +1087,7 @@ MODULE_DEVICE_TABLE(of, bxcan_of_match);\n static struct platform_driver bxcan_driver = {\n \t.driver = {\n \t\t.name = KBUILD_MODNAME,\n-\t\t.pm = \u0026bxcan_pm_ops,\n+\t\t.pm = pm_sleep_ptr(\u0026bxcan_pm_ops),\n \t\t.of_match_table = bxcan_of_match,\n \t},\n \t.probe = bxcan_probe,\ndiff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c\nindex b6c4f02ffb97a..ac81670762c7c 100644\n--- a/drivers/net/can/cc770/cc770_platform.c\n+++ b/drivers/net/can/cc770/cc770_platform.c\n@@ -137,11 +137,11 @@ static int cc770_get_platform_data(struct platform_device *pdev,\n \tstruct cc770_platform_data *pdata = dev_get_platdata(\u0026pdev-\u003edev);\n \n \tpriv-\u003ecan.clock.freq = pdata-\u003eosc_freq;\n+\tpriv-\u003ecpu_interface = pdata-\u003ecir;\n \tif (priv-\u003ecpu_interface \u0026 CPUIF_DSC)\n \t\tpriv-\u003ecan.clock.freq /= 2;\n \tpriv-\u003eclkout = pdata-\u003ecor;\n \tpriv-\u003ebus_config = pdata-\u003ebcr;\n-\tpriv-\u003ecpu_interface = pdata-\u003ecir;\n \n \treturn 0;\n }\n@@ -156,10 +156,13 @@ static int cc770_platform_probe(struct platform_device *pdev)\n \tint err, irq;\n \n \tmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n-\tirq = platform_get_irq(pdev, 0);\n-\tif (!mem || irq \u003c= 0)\n+\tif (!mem)\n \t\treturn -ENODEV;\n \n+\tirq = platform_get_irq(pdev, 0);\n+\tif (irq \u003c 0)\n+\t\treturn irq;\n+\n \tmem_size = resource_size(mem);\n \tif (!request_mem_region(mem-\u003estart, mem_size, pdev-\u003ename))\n \t\treturn -EBUSY;\ndiff --git a/drivers/net/can/ctucanfd/ctucanfd.h b/drivers/net/can/ctucanfd/ctucanfd.h\nindex 0e9904f6a05d6..7dcd7dc507e49 100644\n--- a/drivers/net/can/ctucanfd/ctucanfd.h\n+++ b/drivers/net/can/ctucanfd/ctucanfd.h\n@@ -76,7 +76,7 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr,\n \t\t\tvoid (*set_drvdata_fnc)(struct device *dev,\n \t\t\t\t\t\tstruct net_device *ndev));\n \n-int ctucan_suspend(struct device *dev) __maybe_unused;\n-int ctucan_resume(struct device *dev) __maybe_unused;\n+int ctucan_suspend(struct device *dev);\n+int ctucan_resume(struct device *dev);\n \n #endif /*__CTUCANFD__*/\ndiff --git a/drivers/net/can/ctucanfd/ctucanfd_pci.c b/drivers/net/can/ctucanfd/ctucanfd_pci.c\nindex 4b6db28f7b670..9c9c41c3058c0 100644\n--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c\n+++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c\n@@ -259,7 +259,7 @@ static void ctucan_pci_remove(struct pci_dev *pdev)\n \tkfree(bdata);\n }\n \n-static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);\n+static DEFINE_SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);\n \n static const struct pci_device_id ctucan_pci_tbl[] = {\n \t{PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21,\n@@ -273,7 +273,7 @@ static struct pci_driver ctucan_pci_driver = {\n \t.id_table = ctucan_pci_tbl,\n \t.probe = ctucan_pci_probe,\n \t.remove = ctucan_pci_remove,\n-\t.driver.pm = \u0026ctucan_pci_pm_ops,\n+\t.driver.pm = pm_sleep_ptr(\u0026ctucan_pci_pm_ops),\n };\n \n module_pci_driver(ctucan_pci_driver);\ndiff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c\nindex 70e2577c85416..4962b00ee8ac0 100644\n--- a/drivers/net/can/ctucanfd/ctucanfd_platform.c\n+++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c\n@@ -99,7 +99,7 @@ static void ctucan_platform_remove(struct platform_device *pdev)\n \tfree_candev(ndev);\n }\n \n-static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);\n+static DEFINE_SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);\n \n /* Match table for OF platform binding */\n static const struct of_device_id ctucan_of_match[] = {\n@@ -114,7 +114,7 @@ static struct platform_driver ctucanfd_driver = {\n \t.remove = ctucan_platform_remove,\n \t.driver\t= {\n \t\t.name = DRV_NAME,\n-\t\t.pm = \u0026ctucan_platform_pm_ops,\n+\t\t.pm = pm_sleep_ptr(\u0026ctucan_platform_pm_ops),\n \t\t.of_match_table\t= ctucan_of_match,\n \t},\n };\ndiff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c\nindex 14edec5afb57e..738d5968dfa68 100644\n--- a/drivers/net/can/dev/skb.c\n+++ b/drivers/net/can/dev/skb.c\n@@ -4,6 +4,7 @@\n  * Copyright (C) 2008-2009 Wolfgang Grandegger \u003cwg@grandegger.com\u003e\n  */\n \n+#include \u003clinux/can/can-ml.h\u003e\n #include \u003clinux/can/dev.h\u003e\n #include \u003clinux/module.h\u003e\n #include \u003cnet/can.h\u003e\n@@ -54,6 +55,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,\n \tif (idx \u003e= priv-\u003eecho_skb_max) {\n \t\tnetdev_err(dev, \"%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\\n\",\n \t\t\t   __func__, idx, priv-\u003eecho_skb_max);\n+\t\tdev_kfree_skb_any(skb);\n \t\treturn -EINVAL;\n \t}\n \n@@ -62,7 +64,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,\n \t    (skb-\u003eprotocol != htons(ETH_P_CAN) \u0026\u0026\n \t     skb-\u003eprotocol != htons(ETH_P_CANFD) \u0026\u0026\n \t     skb-\u003eprotocol != htons(ETH_P_CANXL))) {\n-\t\tkfree_skb(skb);\n+\t\tdev_kfree_skb_any(skb);\n \t\treturn 0;\n \t}\n \n@@ -90,7 +92,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,\n \t} else {\n \t\t/* locking problem with netif_stop_queue() ?? */\n \t\tnetdev_err(dev, \"%s: BUG! echo_skb %d is occupied!\\n\", __func__, idx);\n-\t\tkfree_skb(skb);\n+\t\tdev_kfree_skb_any(skb);\n \t\treturn -EBUSY;\n \t}\n \n@@ -227,7 +229,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)\n \n \tcsx = can_skb_ext_add(skb);\n \tif (!csx) {\n-\t\tkfree_skb(skb);\n+\t\tdev_kfree_skb_any(skb);\n \t\tgoto out_error_cc;\n \t}\n \n@@ -258,7 +260,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,\n \n \tcsx = can_skb_ext_add(skb);\n \tif (!csx) {\n-\t\tkfree_skb(skb);\n+\t\tdev_kfree_skb_any(skb);\n \t\tgoto out_error_fd;\n \t}\n \n@@ -296,7 +298,7 @@ struct sk_buff *alloc_canxl_skb(struct net_device *dev,\n \n \tcsx = can_skb_ext_add(skb);\n \tif (!csx) {\n-\t\tkfree_skb(skb);\n+\t\tdev_kfree_skb_any(skb);\n \t\tgoto out_error_xl;\n \t}\n \n@@ -388,7 +390,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)\n \t\tbreak;\n \n \tcase ETH_P_CANXL:\n-\t\tif (!can_is_canxl_skb(skb))\n+\t\tif (!can_cap_enabled(dev, CAN_CAP_XL) || !can_is_canxl_skb(skb))\n \t\t\tgoto inval_skb;\n \t\tbreak;\n \n@@ -402,7 +404,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)\n \treturn false;\n \n inval_skb:\n-\tkfree_skb(skb);\n+\tdev_kfree_skb_any(skb);\n \tdev-\u003estats.tx_dropped++;\n \treturn true;\n }\ndiff --git a/drivers/net/can/esd/esdacc.c b/drivers/net/can/esd/esdacc.c\nindex 73e66f9a3781c..05d41ed34a02e 100644\n--- a/drivers/net/can/esd/esdacc.c\n+++ b/drivers/net/can/esd/esdacc.c\n@@ -62,14 +62,17 @@ static void acc_resetmode_leave(struct acc_core *core)\n \tacc_resetmode_entered(core);\n }\n \n-static void acc_txq_put(struct acc_core *core, u32 acc_id, u32 acc_dlc,\n-\t\t\tconst void *data)\n+static void acc_txq_put(struct acc_core *core, u32 acc_dlc, const void *data)\n {\n \tacc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_1,\n \t\t\t   *((const u32 *)(data + 4)));\n \tacc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_0,\n \t\t\t   *((const u32 *)data));\n \tacc_write32(core, ACC_CORE_OF_TXFIFO_DLC, acc_dlc);\n+}\n+\n+static void acc_txq_start(struct acc_core *core, u32 acc_id)\n+{\n \t/* CAN id must be written at last. This write starts TX. */\n \tacc_write32(core, ACC_CORE_OF_TXFIFO_ID, acc_id);\n }\n@@ -287,11 +290,12 @@ netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev)\n \t\tacc_id = cf-\u003ecan_id \u0026 CAN_SFF_MASK;\n \t}\n \n-\tcan_put_echo_skb(skb, netdev, core-\u003etx_fifo_head, 0);\n+\tacc_txq_put(core, acc_dlc, cf-\u003edata);\n \n+\tcan_put_echo_skb(skb, netdev, core-\u003etx_fifo_head, 0);\n \tcore-\u003etx_fifo_head = acc_tx_fifo_next(core, tx_fifo_head);\n \n-\tacc_txq_put(core, acc_id, acc_dlc, cf-\u003edata);\n+\tacc_txq_start(core, acc_id);\n \n \treturn NETDEV_TX_OK;\n }\ndiff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c\nindex 86b40abe9e767..30ae7c344a05e 100644\n--- a/drivers/net/can/flexcan/flexcan-core.c\n+++ b/drivers/net/can/flexcan/flexcan-core.c\n@@ -1986,6 +1986,7 @@ static int flexcan_setup_stop_mode_gpr(struct platform_device *pdev)\n \t\t\"gpr %s req_gpr=0x02%x req_bit=%u\\n\",\n \t\tgpr_np-\u003efull_name, priv-\u003estm.req_gpr, priv-\u003estm.req_bit);\n \n+\tof_node_put(gpr_np);\n \treturn 0;\n \n out_put_node:\ndiff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c\nindex ce12fa6df56d5..1b4944d1d06dd 100644\n--- a/drivers/net/can/grcan.c\n+++ b/drivers/net/can/grcan.c\n@@ -10,8 +10,8 @@\n  * Full documentation of the GRCAN core can be found here:\n  * http://www.gaisler.com/products/grlib/grip.pdf\n  *\n- * See \"Documentation/devicetree/bindings/net/can/grcan.txt\" for information on\n- * open firmware properties.\n+ * See \"Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml\"\n+ * for information on open firmware properties.\n  *\n  * See \"Documentation/ABI/testing/sysfs-class-net-grcan\" for information on the\n  * sysfs interface.\ndiff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c\nindex d8c9bfb202304..a0597db720864 100644\n--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c\n+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c\n@@ -1739,6 +1739,7 @@ static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)\n \t\t\tiowrite32(0, can-\u003ereg_base + KVASER_PCIEFD_KCAN_IEN_REG);\n \t\t\tkvaser_pciefd_pwm_stop(can);\n \t\t\tkvaser_pciefd_devlink_port_unregister(can);\n+\t\t\ttimer_shutdown_sync(\u0026can-\u003ebec_poll_timer);\n \t\t\tfree_candev(can-\u003ecan.dev);\n \t\t}\n \t}\n@@ -1879,7 +1880,7 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)\n \t\tstruct kvaser_pciefd_can *can = pcie-\u003ecan[i];\n \n \t\tunregister_candev(can-\u003ecan.dev);\n-\t\ttimer_delete(\u0026can-\u003ebec_poll_timer);\n+\t\ttimer_shutdown_sync(\u0026can-\u003ebec_poll_timer);\n \t\tkvaser_pciefd_pwm_stop(can);\n \t\tkvaser_pciefd_devlink_port_unregister(can);\n \t}\ndiff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c\nindex d11a7c88fc32f..d31179312026b 100644\n--- a/drivers/net/can/m_can/m_can_pci.c\n+++ b/drivers/net/can/m_can/m_can_pci.c\n@@ -169,17 +169,17 @@ static void m_can_pci_remove(struct pci_dev *pci)\n \tpci_free_irq_vectors(pci);\n }\n \n-static __maybe_unused int m_can_pci_suspend(struct device *dev)\n+static int m_can_pci_suspend(struct device *dev)\n {\n \treturn m_can_class_suspend(dev);\n }\n \n-static __maybe_unused int m_can_pci_resume(struct device *dev)\n+static int m_can_pci_resume(struct device *dev)\n {\n \treturn m_can_class_resume(dev);\n }\n \n-static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,\n+static DEFINE_SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,\n \t\t\t m_can_pci_suspend, m_can_pci_resume);\n \n static const struct pci_device_id m_can_pci_id_table[] = {\n@@ -195,7 +195,7 @@ static struct pci_driver m_can_pci_driver = {\n \t.remove = m_can_pci_remove,\n \t.id_table = m_can_pci_id_table,\n \t.driver = {\n-\t\t.pm = \u0026m_can_pci_pm_ops,\n+\t\t.pm = pm_sleep_ptr(\u0026m_can_pci_pm_ops),\n \t},\n };\n \ndiff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c\nindex fcc37b73ed436..c643879673680 100644\n--- a/drivers/net/can/rcar/rcar_canfd.c\n+++ b/drivers/net/can/rcar/rcar_canfd.c\n@@ -132,9 +132,9 @@\n #define RCANFD_CCTR_BEIE\t\tBIT(8)\n #define RCANFD_CCTR_CSLPR\t\tBIT(2)\n #define RCANFD_CCTR_CHMDC_MASK\t\t(0x3)\n-#define RCANFD_CCTR_CHDMC_COPM\t\t(0x0)\n-#define RCANFD_CCTR_CHDMC_CRESET\t(0x1)\n-#define RCANFD_CCTR_CHDMC_CHLT\t\t(0x2)\n+#define RCANFD_CCTR_CHMDC_COPM\t\t(0x0)\n+#define RCANFD_CCTR_CHMDC_CRESET\t(0x1)\n+#define RCANFD_CCTR_CHMDC_CHLT\t\t(0x2)\n \n /* RSCFDnCFDCmSTS / RSCFDnCmSTS */\n #define RCANFD_CSTS_COMSTS\t\tBIT(7)\n@@ -436,7 +436,6 @@ struct rcar_canfd_hw_info {\n \tu8 rnc_field_width;\n \tu8 max_aflpn;\n \tu8 max_cftml;\n-\tu8 max_channels;\n \tu8 postdiv;\n \t/* hardware features */\n \tunsigned shared_global_irqs:1;\t/* Has shared global irqs */\n@@ -444,6 +443,8 @@ struct rcar_canfd_hw_info {\n \tunsigned ch_interface_mode:1;\t/* Has channel interface mode */\n \tunsigned shared_can_regs:1;\t/* Has shared classical can registers */\n \tunsigned external_clk:1;\t/* Has external clock */\n+\tunsigned fcan_pclk:1;\t\t/* Has fcan sourced from pclk. */\n+\tunsigned fixed_canfd:1;\t\t/* Has mode fixed to canfd. */\n };\n \n /* Channel priv data */\n@@ -476,6 +477,7 @@ struct rcar_canfd_global {\n \tstruct reset_control *rstc1;\n \tstruct reset_control *rstc2;\n \tconst struct rcar_canfd_hw_info *info;\n+\tu8 max_channels;\n };\n \n /* CAN FD mode nominal rate constants */\n@@ -611,12 +613,13 @@ static const struct rcar_canfd_hw_info rcar_gen3_hw_info = {\n \t.rnc_field_width = 8,\n \t.max_aflpn = 31,\n \t.max_cftml = 15,\n-\t.max_channels = 2,\n \t.postdiv = 2,\n \t.shared_global_irqs = 1,\n \t.ch_interface_mode = 0,\n \t.shared_can_regs = 0,\n \t.external_clk = 1,\n+\t.fcan_pclk = 0,\n+\t.fixed_canfd = 0,\n };\n \n static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {\n@@ -628,12 +631,13 @@ static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {\n \t.rnc_field_width = 16,\n \t.max_aflpn = 127,\n \t.max_cftml = 31,\n-\t.max_channels = 8,\n \t.postdiv = 2,\n \t.shared_global_irqs = 1,\n \t.ch_interface_mode = 1,\n \t.shared_can_regs = 1,\n \t.external_clk = 1,\n+\t.fcan_pclk = 0,\n+\t.fixed_canfd = 0,\n };\n \n static const struct rcar_canfd_hw_info rzg2l_hw_info = {\n@@ -645,12 +649,32 @@ static const struct rcar_canfd_hw_info rzg2l_hw_info = {\n \t.rnc_field_width = 8,\n \t.max_aflpn = 31,\n \t.max_cftml = 15,\n-\t.max_channels = 2,\n \t.postdiv = 1,\n \t.multi_channel_irqs = 1,\n \t.ch_interface_mode = 0,\n \t.shared_can_regs = 0,\n \t.external_clk = 1,\n+\t.fcan_pclk = 0,\n+\t.fixed_canfd = 0,\n+};\n+\n+static const struct rcar_canfd_hw_info r9a08g045_hw_info = {\n+\t.nom_bittiming = \u0026rcar_canfd_gen4_nom_bittiming_const,\n+\t.data_bittiming = \u0026rcar_canfd_gen4_data_bittiming_const,\n+\t.tdc_const = \u0026rcar_canfd_gen4_tdc_const,\n+\t.regs = \u0026rcar_gen4_regs,\n+\t.sh = \u0026rcar_gen4_shift_data,\n+\t.rnc_field_width = 16,\n+\t.max_aflpn = 15,\n+\t.max_cftml = 31,\n+\t.postdiv = 2,\n+\t.shared_global_irqs = 0,\n+\t.multi_channel_irqs = 1,\n+\t.ch_interface_mode = 1,\n+\t.shared_can_regs = 1,\n+\t.external_clk = 1,\n+\t.fcan_pclk = 1,\n+\t.fixed_canfd = 1,\n };\n \n static const struct rcar_canfd_hw_info r9a09g047_hw_info = {\n@@ -662,12 +686,13 @@ static const struct rcar_canfd_hw_info r9a09g047_hw_info = {\n \t.rnc_field_width = 16,\n \t.max_aflpn = 63,\n \t.max_cftml = 31,\n-\t.max_channels = 6,\n \t.postdiv = 1,\n \t.multi_channel_irqs = 1,\n \t.ch_interface_mode = 1,\n \t.shared_can_regs = 1,\n \t.external_clk = 0,\n+\t.fcan_pclk = 0,\n+\t.fixed_canfd = 0,\n };\n \n static const struct rcar_canfd_hw_info r9a09g077_hw_info = {\n@@ -679,12 +704,13 @@ static const struct rcar_canfd_hw_info r9a09g077_hw_info = {\n \t.rnc_field_width = 16,\n \t.max_aflpn = 15,\n \t.max_cftml = 31,\n-\t.max_channels = 2,\n \t.postdiv = 1,\n \t.multi_channel_irqs = 1,\n \t.ch_interface_mode = 1,\n \t.shared_can_regs = 1,\n \t.external_clk = 1,\n+\t.fcan_pclk = 0,\n+\t.fixed_canfd = 0,\n };\n \n /* Helper functions */\n@@ -822,13 +848,13 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)\n \t}\n \n \t/* Transition all Channels to reset mode */\n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\trcar_canfd_clear_bit(gpriv-\u003ebase,\n \t\t\t\t     RCANFD_CCTR(ch), RCANFD_CCTR_CSLPR);\n \n \t\trcar_canfd_update_bit(gpriv-\u003ebase, RCANFD_CCTR(ch),\n \t\t\t\t      RCANFD_CCTR_CHMDC_MASK,\n-\t\t\t\t      RCANFD_CCTR_CHDMC_CRESET);\n+\t\t\t\t      RCANFD_CCTR_CHMDC_CRESET);\n \n \t\t/* Ensure Channel reset mode */\n \t\terr = readl_poll_timeout((gpriv-\u003ebase + RCANFD_CSTS(ch)), sts,\n@@ -840,6 +866,9 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)\n \t\t}\n \n \t\t/* Set the controller into appropriate mode */\n+\t\tif (gpriv-\u003einfo-\u003efixed_canfd)\n+\t\t\tcontinue;\n+\n \t\tif (gpriv-\u003einfo-\u003ech_interface_mode) {\n \t\t\t/* Do not set CLOE and FDOE simultaneously */\n \t\t\tif (!gpriv-\u003efdmode) {\n@@ -887,7 +916,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)\n \trcar_canfd_set_bit(gpriv-\u003ebase, RCANFD_GCFG, cfg);\n \n \t/* Channel configuration settings */\n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\trcar_canfd_set_bit(gpriv-\u003ebase, RCANFD_CCTR(ch),\n \t\t\t\t   RCANFD_CCTR_ERRD);\n \t\trcar_canfd_update_bit(gpriv-\u003ebase, RCANFD_CCTR(ch),\n@@ -1258,7 +1287,7 @@ static irqreturn_t rcar_canfd_global_err_interrupt(int irq, void *dev_id)\n \tstruct rcar_canfd_global *gpriv = dev_id;\n \tu32 ch;\n \n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels)\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels)\n \t\trcar_canfd_handle_global_err(gpriv, ch);\n \n \treturn IRQ_HANDLED;\n@@ -1290,7 +1319,7 @@ static irqreturn_t rcar_canfd_global_receive_fifo_interrupt(int irq, void *dev_i\n \tstruct rcar_canfd_global *gpriv = dev_id;\n \tu32 ch;\n \n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels)\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels)\n \t\trcar_canfd_handle_global_receive(gpriv, ch);\n \n \treturn IRQ_HANDLED;\n@@ -1304,7 +1333,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)\n \t/* Global error interrupts still indicate a condition specific\n \t * to a channel. RxFIFO interrupt is a global interrupt.\n \t */\n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\trcar_canfd_handle_global_err(gpriv, ch);\n \t\trcar_canfd_handle_global_receive(gpriv, ch);\n \t}\n@@ -1400,7 +1429,7 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)\n \tu32 ch;\n \n \t/* Common FIFO is a per channel resource */\n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\trcar_canfd_handle_channel_err(gpriv, ch);\n \t\trcar_canfd_handle_channel_tx(gpriv, ch);\n \t}\n@@ -1504,7 +1533,7 @@ static int rcar_canfd_start(struct net_device *ndev)\n \n \t/* Set channel to Operational mode */\n \trcar_canfd_update_bit(priv-\u003ebase, RCANFD_CCTR(ch),\n-\t\t\t      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_COPM);\n+\t\t\t      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHMDC_COPM);\n \n \t/* Verify channel mode change */\n \terr = readl_poll_timeout((priv-\u003ebase + RCANFD_CSTS(ch)), sts,\n@@ -1578,7 +1607,7 @@ static void rcar_canfd_stop(struct net_device *ndev)\n \n \t/* Transition to channel reset mode  */\n \trcar_canfd_update_bit(priv-\u003ebase, RCANFD_CCTR(ch),\n-\t\t\t      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_CRESET);\n+\t\t\t      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHMDC_CRESET);\n \n \t/* Check Channel reset mode */\n \terr = readl_poll_timeout((priv-\u003ebase + RCANFD_CSTS(ch)), sts,\n@@ -2037,7 +2066,7 @@ static int rcar_canfd_global_init(struct rcar_canfd_global *gpriv)\n \trcar_canfd_configure_controller(gpriv);\n \n \t/* Configure per channel attributes */\n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\t/* Configure Channel's Rx fifo */\n \t\trcar_canfd_configure_rx(gpriv, ch);\n \n@@ -2110,14 +2139,18 @@ static int rcar_canfd_probe(struct platform_device *pdev)\n \tbool fdmode = true;\t\t\t/* CAN FD only mode - default */\n \tchar name[9] = \"channelX\";\n \tu32 ch, fcan_freq;\n+\tu8 max_channels;\n \tint i;\n \n \tinfo = of_device_get_match_data(dev);\n+\tmax_channels = of_get_child_count(dev-\u003eof_node);\n+\tif (max_channels \u003e RCANFD_NUM_CHANNELS)\n+\t\treturn -EINVAL;\n \n \tif (of_property_read_bool(dev-\u003eof_node, \"renesas,no-can-fd\"))\n \t\tfdmode = false;\t\t\t/* Classical CAN only mode */\n \n-\tfor (i = 0; i \u003c info-\u003emax_channels; ++i) {\n+\tfor (i = 0; i \u003c max_channels; ++i) {\n \t\tname[7] = '0' + i;\n \t\tof_child = of_get_available_child_by_name(dev-\u003eof_node, name);\n \t\tif (of_child) {\n@@ -2164,6 +2197,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)\n \tgpriv-\u003epdev = pdev;\n \tgpriv-\u003echannels_mask = channels_mask;\n \tgpriv-\u003efdmode = fdmode;\n+\tgpriv-\u003emax_channels = max_channels;\n \tgpriv-\u003einfo = info;\n \n \tif (of_property_read_bool(dev-\u003eof_node, \"renesas,fd-only\"))\n@@ -2190,13 +2224,20 @@ static int rcar_canfd_probe(struct platform_device *pdev)\n \t */\n \tgpriv-\u003ecan_clk = devm_clk_get(dev, \"can_clk\");\n \tif (IS_ERR(gpriv-\u003ecan_clk) || (clk_get_rate(gpriv-\u003ecan_clk) == 0)) {\n-\t\tgpriv-\u003ecan_clk = devm_clk_get(dev, \"canfd\");\n-\t\tif (IS_ERR(gpriv-\u003ecan_clk))\n-\t\t\treturn dev_err_probe(dev, PTR_ERR(gpriv-\u003ecan_clk),\n-\t\t\t\t\t     \"cannot get canfd clock\\n\");\n+\t\tif (info-\u003efcan_pclk) {\n+\t\t\tfcan_freq = clk_get_rate(gpriv-\u003eclkp);\n+\t\t\tgpriv-\u003ecan_clk = NULL;\n+\t\t} else {\n+\t\t\tgpriv-\u003ecan_clk = devm_clk_get(dev, \"canfd\");\n+\t\t\tif (IS_ERR(gpriv-\u003ecan_clk))\n+\t\t\t\treturn dev_err_probe(dev, PTR_ERR(gpriv-\u003ecan_clk),\n+\t\t\t\t\t\t     \"cannot get canfd clock\\n\");\n+\n+\t\t\tfcan_freq = clk_get_rate(gpriv-\u003ecan_clk);\n+\t\t}\n \n \t\t/* CANFD clock may be further divided within the IP */\n-\t\tfcan_freq = clk_get_rate(gpriv-\u003ecan_clk) / info-\u003epostdiv;\n+\t\tfcan_freq /= info-\u003epostdiv;\n \t} else {\n \t\tfcan_freq = clk_get_rate(gpriv-\u003ecan_clk);\n \t\tgpriv-\u003eextclk = gpriv-\u003einfo-\u003eexternal_clk;\n@@ -2258,7 +2299,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)\n \tif (err)\n \t\tgoto fail_mode;\n \n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, info-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\terr = rcar_canfd_channel_probe(gpriv, ch, fcan_freq,\n \t\t\t\t\t       transceivers[ch]);\n \t\tif (err)\n@@ -2272,7 +2313,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)\n \treturn 0;\n \n fail_channel:\n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, info-\u003emax_channels)\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels)\n \t\trcar_canfd_channel_remove(gpriv, ch);\n fail_mode:\n \trcar_canfd_global_deinit(gpriv, false);\n@@ -2285,7 +2326,7 @@ static void rcar_canfd_remove(struct platform_device *pdev)\n \tstruct rcar_canfd_global *gpriv = platform_get_drvdata(pdev);\n \tu32 ch;\n \n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\trcar_canfd_disable_channel_interrupts(gpriv-\u003ech[ch]);\n \t\trcar_canfd_channel_remove(gpriv, ch);\n \t}\n@@ -2299,7 +2340,7 @@ static int rcar_canfd_suspend(struct device *dev)\n \tint err;\n \tu32 ch;\n \n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\tstruct rcar_canfd_channel *priv = gpriv-\u003ech[ch];\n \t\tstruct net_device *ndev = priv-\u003endev;\n \n@@ -2336,7 +2377,7 @@ static int rcar_canfd_resume(struct device *dev)\n \t\treturn err;\n \t}\n \n-\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003einfo-\u003emax_channels) {\n+\tfor_each_set_bit(ch, \u0026gpriv-\u003echannels_mask, gpriv-\u003emax_channels) {\n \t\tstruct rcar_canfd_channel *priv = gpriv-\u003ech[ch];\n \t\tstruct net_device *ndev = priv-\u003endev;\n \n@@ -2361,6 +2402,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,\n \n static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {\n \t{ .compatible = \"renesas,r8a779a0-canfd\", .data = \u0026rcar_gen4_hw_info },\n+\t{ .compatible = \"renesas,r9a08g045-canfd\", .data = \u0026r9a08g045_hw_info },\n+\t{ .compatible = \"renesas,r9a08g046-canfd\", .data = \u0026r9a08g045_hw_info },\n \t{ .compatible = \"renesas,r9a09g047-canfd\", .data = \u0026r9a09g047_hw_info },\n \t{ .compatible = \"renesas,r9a09g077-canfd\", .data = \u0026r9a09g077_hw_info },\n \t{ .compatible = \"renesas,rcar-gen3-canfd\", .data = \u0026rcar_gen3_hw_info },\ndiff --git a/drivers/net/can/softing/Kconfig b/drivers/net/can/softing/Kconfig\ndeleted file mode 100644\nindex 8afd7d0a1000a..0000000000000\n--- a/drivers/net/can/softing/Kconfig\n+++ /dev/null\n@@ -1,31 +0,0 @@\n-# SPDX-License-Identifier: GPL-2.0-only\n-config CAN_SOFTING\n-\ttristate \"Softing Gmbh CAN generic support\"\n-\tdepends on HAS_IOMEM\n-\thelp\n-\t  Support for CAN cards from Softing Gmbh \u0026 some cards\n-\t  from Vector Gmbh.\n-\t  Softing Gmbh CAN cards come with 1 or 2 physical buses.\n-\t  Those cards typically use Dual Port RAM to communicate\n-\t  with the host CPU. The interface is then identical for PCI\n-\t  and PCMCIA cards. This driver operates on a platform device,\n-\t  which has been created by softing_cs or softing_pci driver.\n-\t  Warning:\n-\t  The API of the card does not allow fine control per bus, but\n-\t  controls the 2 buses on the card together.\n-\t  As such, some actions (start/stop/busoff recovery) on 1 bus\n-\t  must bring down the other bus too temporarily.\n-\n-config CAN_SOFTING_CS\n-\ttristate \"Softing Gmbh CAN pcmcia cards\"\n-\tdepends on PCMCIA\n-\tdepends on CAN_SOFTING\n-\thelp\n-\t  Support for PCMCIA cards from Softing Gmbh \u0026 some cards\n-\t  from Vector Gmbh.\n-\t  You need firmware for these, which you can get at\n-\t  https://github.com/linux-can/can-firmware\n-\t  This version of the driver is written against\n-\t  firmware version 4.6 (softing-fw-4.6-binaries.tar.gz)\n-\t  In order to use the card as CAN device, you need the Softing generic\n-\t  support too.\ndiff --git a/drivers/net/can/softing/Makefile b/drivers/net/can/softing/Makefile\ndeleted file mode 100644\nindex c511540003779..0000000000000\n--- a/drivers/net/can/softing/Makefile\n+++ /dev/null\n@@ -1,5 +0,0 @@\n-# SPDX-License-Identifier: GPL-2.0-only\n-\n-softing-y := softing_main.o softing_fw.o\n-obj-$(CONFIG_CAN_SOFTING) += softing.o\n-obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o\ndiff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h\ndeleted file mode 100644\nindex 2893007ea05e1..0000000000000\n--- a/drivers/net/can/softing/softing.h\n+++ /dev/null\n@@ -1,168 +0,0 @@\n-/* SPDX-License-Identifier: GPL-2.0 */\n-/*\n- * softing common interfaces\n- *\n- * by Kurt Van Dijck, 2008-2010\n- */\n-\n-#include \u003clinux/atomic.h\u003e\n-#include \u003clinux/netdevice.h\u003e\n-#include \u003clinux/ktime.h\u003e\n-#include \u003clinux/mutex.h\u003e\n-#include \u003clinux/spinlock.h\u003e\n-#include \u003clinux/can.h\u003e\n-#include \u003clinux/can/dev.h\u003e\n-\n-#include \"softing_platform.h\"\n-\n-struct softing;\n-\n-struct softing_priv {\n-\tstruct can_priv can; /* must be the first member! */\n-\tstruct net_device *netdev;\n-\tstruct softing *card;\n-\tstruct {\n-\t\tint pending;\n-\t\t/* variables which hold the circular buffer */\n-\t\tint echo_put;\n-\t\tint echo_get;\n-\t} tx;\n-\tstruct can_bittiming_const btr_const;\n-\tint index;\n-\tuint8_t output;\n-\tuint16_t chip;\n-};\n-#define netdev2softing(netdev)\t((struct softing_priv *)netdev_priv(netdev))\n-\n-struct softing {\n-\tconst struct softing_platform_data *pdat;\n-\tstruct platform_device *pdev;\n-\tstruct net_device *net[2];\n-\tspinlock_t spin; /* protect this structure \u0026 DPRAM access */\n-\tktime_t ts_ref;\n-\tktime_t ts_overflow; /* timestamp overflow value, in ktime */\n-\n-\tstruct {\n-\t\t/* indication of firmware status */\n-\t\tint up;\n-\t\t/* protection of the 'up' variable */\n-\t\tstruct mutex lock;\n-\t} fw;\n-\tstruct {\n-\t\tint nr;\n-\t\tint requested;\n-\t\tint svc_count;\n-\t\tunsigned int dpram_position;\n-\t} irq;\n-\tstruct {\n-\t\tint pending;\n-\t\tint last_bus;\n-\t\t/*\n-\t\t * keep the bus that last tx'd a message,\n-\t\t * in order to let every netdev queue resume\n-\t\t */\n-\t} tx;\n-\t__iomem uint8_t *dpram;\n-\tunsigned long dpram_phys;\n-\tunsigned long dpram_size;\n-\tstruct {\n-\t\tuint16_t fw_version, hw_version, license, serial;\n-\t\tuint16_t chip[2];\n-\t\tunsigned int freq; /* remote cpu's operating frequency */\n-\t} id;\n-};\n-\n-int softing_default_output(struct net_device *netdev);\n-\n-ktime_t softing_raw2ktime(struct softing *card, u32 raw);\n-\n-int softing_chip_poweron(struct softing *card);\n-\n-int softing_bootloader_command(struct softing *card, int16_t cmd,\n-\t\t\t       const char *msg);\n-\n-/* Load firmware after reset */\n-int softing_load_fw(const char *file, struct softing *card,\n-\t\t    __iomem uint8_t *virt, unsigned int size, int offset);\n-\n-/* Load final application firmware after bootloader */\n-int softing_load_app_fw(const char *file, struct softing *card);\n-\n-/*\n- * enable or disable irq\n- * only called with fw.lock locked\n- */\n-int softing_enable_irq(struct softing *card, int enable);\n-\n-/* start/stop 1 bus on card */\n-int softing_startstop(struct net_device *netdev, int up);\n-\n-/* netif_rx() */\n-int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,\n-\t\t      ktime_t ktime);\n-\n-/* SOFTING DPRAM mappings */\n-#define DPRAM_RX\t\t0x0000\n-\t#define DPRAM_RX_SIZE\t32\n-\t#define DPRAM_RX_CNT\t16\n-#define DPRAM_RX_RD\t\t0x0201\t/* uint8_t */\n-#define DPRAM_RX_WR\t\t0x0205\t/* uint8_t */\n-#define DPRAM_RX_LOST\t\t0x0207\t/* uint8_t */\n-\n-#define DPRAM_FCT_PARAM\t\t0x0300\t/* int16_t [20] */\n-#define DPRAM_FCT_RESULT\t0x0328\t/* int16_t */\n-#define DPRAM_FCT_HOST\t\t0x032b\t/* uint16_t */\n-\n-#define DPRAM_INFO_BUSSTATE\t0x0331\t/* uint16_t */\n-#define DPRAM_INFO_BUSSTATE2\t0x0335\t/* uint16_t */\n-#define DPRAM_INFO_ERRSTATE\t0x0339\t/* uint16_t */\n-#define DPRAM_INFO_ERRSTATE2\t0x033d\t/* uint16_t */\n-#define DPRAM_RESET\t\t0x0341\t/* uint16_t */\n-#define DPRAM_CLR_RECV_FIFO\t0x0345\t/* uint16_t */\n-#define DPRAM_RESET_TIME\t0x034d\t/* uint16_t */\n-#define DPRAM_TIME\t\t0x0350\t/* uint64_t */\n-#define DPRAM_WR_START\t\t0x0358\t/* uint8_t */\n-#define DPRAM_WR_END\t\t0x0359\t/* uint8_t */\n-#define DPRAM_RESET_RX_FIFO\t0x0361\t/* uint16_t */\n-#define DPRAM_RESET_TX_FIFO\t0x0364\t/* uint8_t */\n-#define DPRAM_READ_FIFO_LEVEL\t0x0365\t/* uint8_t */\n-#define DPRAM_RX_FIFO_LEVEL\t0x0366\t/* uint16_t */\n-#define DPRAM_TX_FIFO_LEVEL\t0x0366\t/* uint16_t */\n-\n-#define DPRAM_TX\t\t0x0400\t/* uint16_t */\n-\t#define DPRAM_TX_SIZE\t16\n-\t#define DPRAM_TX_CNT\t32\n-#define DPRAM_TX_RD\t\t0x0601\t/* uint8_t */\n-#define DPRAM_TX_WR\t\t0x0605\t/* uint8_t */\n-\n-#define DPRAM_COMMAND\t\t0x07e0\t/* uint16_t */\n-#define DPRAM_RECEIPT\t\t0x07f0\t/* uint16_t */\n-#define DPRAM_IRQ_TOHOST\t0x07fe\t/* uint8_t */\n-#define DPRAM_IRQ_TOCARD\t0x07ff\t/* uint8_t */\n-\n-#define DPRAM_V2_RESET\t\t0x0e00\t/* uint8_t */\n-#define DPRAM_V2_IRQ_TOHOST\t0x0e02\t/* uint8_t */\n-\n-#define TXMAX\t(DPRAM_TX_CNT - 1)\n-\n-/* DPRAM return codes */\n-#define RES_NONE\t0\n-#define RES_OK\t\t1\n-#define RES_NOK\t\t2\n-#define RES_UNKNOWN\t3\n-/* DPRAM flags */\n-#define CMD_TX\t\t0x01\n-#define CMD_ACK\t\t0x02\n-#define CMD_XTD\t\t0x04\n-#define CMD_RTR\t\t0x08\n-#define CMD_ERR\t\t0x10\n-#define CMD_BUS2\t0x80\n-\n-/* returned fifo entry bus state masks */\n-#define SF_MASK_BUSOFF\t\t0x80\n-#define SF_MASK_EPASSIVE\t0x60\n-\n-/* bus states */\n-#define STATE_BUSOFF\t2\n-#define STATE_EPASSIVE\t1\n-#define STATE_EACTIVE\t0\ndiff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c\ndeleted file mode 100644\nindex 3cea14cf055ad..0000000000000\n--- a/drivers/net/can/softing/softing_cs.c\n+++ /dev/null\n@@ -1,335 +0,0 @@\n-// SPDX-License-Identifier: GPL-2.0-only\n-/*\n- * Copyright (C) 2008-2010\n- *\n- * - Kurt Van Dijck, EIA Electronics\n- */\n-\n-#include \u003clinux/module.h\u003e\n-#include \u003clinux/kernel.h\u003e\n-#include \u003clinux/slab.h\u003e\n-\n-#include \u003cpcmcia/cistpl.h\u003e\n-#include \u003cpcmcia/ds.h\u003e\n-\n-#include \"softing_platform.h\"\n-\n-static int softingcs_index;\n-static DEFINE_SPINLOCK(softingcs_index_lock);\n-\n-static int softingcs_reset(struct platform_device *pdev, int v);\n-static int softingcs_enable_irq(struct platform_device *pdev, int v);\n-\n-/*\n- * platform_data descriptions\n- */\n-#define MHZ (1000*1000)\n-static const struct softing_platform_data softingcs_platform_data[] = {\n-{\n-\t.name = \"CANcard\",\n-\t.manf = 0x0168, .prod = 0x001,\n-\t.generation = 1,\n-\t.nbus = 2,\n-\t.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,\n-\t.dpram_size = 0x0800,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancard.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = softingcs_enable_irq,\n-}, {\n-\t.name = \"CANcard-NEC\",\n-\t.manf = 0x0168, .prod = 0x002,\n-\t.generation = 1,\n-\t.nbus = 2,\n-\t.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,\n-\t.dpram_size = 0x0800,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancard.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = softingcs_enable_irq,\n-}, {\n-\t.name = \"CANcard-SJA\",\n-\t.manf = 0x0168, .prod = 0x004,\n-\t.generation = 1,\n-\t.nbus = 2,\n-\t.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,\n-\t.dpram_size = 0x0800,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cansja.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = softingcs_enable_irq,\n-}, {\n-\t.name = \"CANcard-2\",\n-\t.manf = 0x0168, .prod = 0x005,\n-\t.generation = 2,\n-\t.nbus = 2,\n-\t.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,\n-\t.dpram_size = 0x1000,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard2.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard2.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancrd2.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = NULL,\n-}, {\n-\t.name = \"Vector-CANcard\",\n-\t.manf = 0x0168, .prod = 0x081,\n-\t.generation = 1,\n-\t.nbus = 2,\n-\t.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,\n-\t.dpram_size = 0x0800,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancard.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = softingcs_enable_irq,\n-}, {\n-\t.name = \"Vector-CANcard-SJA\",\n-\t.manf = 0x0168, .prod = 0x084,\n-\t.generation = 1,\n-\t.nbus = 2,\n-\t.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,\n-\t.dpram_size = 0x0800,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cansja.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = softingcs_enable_irq,\n-}, {\n-\t.name = \"Vector-CANcard-2\",\n-\t.manf = 0x0168, .prod = 0x085,\n-\t.generation = 2,\n-\t.nbus = 2,\n-\t.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,\n-\t.dpram_size = 0x1000,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard2.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard2.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancrd2.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = NULL,\n-}, {\n-\t.name = \"EDICcard-NEC\",\n-\t.manf = 0x0168, .prod = 0x102,\n-\t.generation = 1,\n-\t.nbus = 2,\n-\t.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,\n-\t.dpram_size = 0x0800,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancard.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = softingcs_enable_irq,\n-}, {\n-\t.name = \"EDICcard-2\",\n-\t.manf = 0x0168, .prod = 0x105,\n-\t.generation = 2,\n-\t.nbus = 2,\n-\t.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,\n-\t.dpram_size = 0x1000,\n-\t.boot = {0x0000, 0x000000, fw_dir \"bcard2.bin\",},\n-\t.load = {0x0120, 0x00f600, fw_dir \"ldcard2.bin\",},\n-\t.app = {0x0010, 0x0d0000, fw_dir \"cancrd2.bin\",},\n-\t.reset = softingcs_reset,\n-\t.enable_irq = NULL,\n-}, {\n-\t0, 0,\n-},\n-};\n-\n-MODULE_FIRMWARE(fw_dir \"bcard.bin\");\n-MODULE_FIRMWARE(fw_dir \"ldcard.bin\");\n-MODULE_FIRMWARE(fw_dir \"cancard.bin\");\n-MODULE_FIRMWARE(fw_dir \"cansja.bin\");\n-\n-MODULE_FIRMWARE(fw_dir \"bcard2.bin\");\n-MODULE_FIRMWARE(fw_dir \"ldcard2.bin\");\n-MODULE_FIRMWARE(fw_dir \"cancrd2.bin\");\n-\n-static const struct softing_platform_data\n-*softingcs_find_platform_data(unsigned int manf, unsigned int prod)\n-{\n-\tconst struct softing_platform_data *lp;\n-\n-\tfor (lp = softingcs_platform_data; lp-\u003emanf; ++lp) {\n-\t\tif ((lp-\u003emanf == manf) \u0026\u0026 (lp-\u003eprod == prod))\n-\t\t\treturn lp;\n-\t}\n-\treturn NULL;\n-}\n-\n-/*\n- * platformdata callbacks\n- */\n-static int softingcs_reset(struct platform_device *pdev, int v)\n-{\n-\tstruct pcmcia_device *pcmcia = to_pcmcia_dev(pdev-\u003edev.parent);\n-\n-\tdev_dbg(\u0026pdev-\u003edev, \"pcmcia config [2] %02x\\n\", v ? 0 : 0x20);\n-\treturn pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);\n-}\n-\n-static int softingcs_enable_irq(struct platform_device *pdev, int v)\n-{\n-\tstruct pcmcia_device *pcmcia = to_pcmcia_dev(pdev-\u003edev.parent);\n-\n-\tdev_dbg(\u0026pdev-\u003edev, \"pcmcia config [0] %02x\\n\", v ? 0x60 : 0);\n-\treturn pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);\n-}\n-\n-/*\n- * pcmcia check\n- */\n-static int softingcs_probe_config(struct pcmcia_device *pcmcia, void *priv_data)\n-{\n-\tstruct softing_platform_data *pdat = priv_data;\n-\tstruct resource *pres;\n-\tint memspeed = 0;\n-\n-\tWARN_ON(!pdat);\n-\tpres = pcmcia-\u003eresource[PCMCIA_IOMEM_0];\n-\tif (resource_size(pres) \u003c 0x1000)\n-\t\treturn -ERANGE;\n-\n-\tpres-\u003eflags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;\n-\tif (pdat-\u003egeneration \u003c 2) {\n-\t\tpres-\u003eflags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;\n-\t\tmemspeed = 3;\n-\t} else {\n-\t\tpres-\u003eflags |= WIN_DATA_WIDTH_16;\n-\t}\n-\treturn pcmcia_request_window(pcmcia, pres, memspeed);\n-}\n-\n-static void softingcs_remove(struct pcmcia_device *pcmcia)\n-{\n-\tstruct platform_device *pdev = pcmcia-\u003epriv;\n-\n-\t/* free bits */\n-\tplatform_device_unregister(pdev);\n-\t/* release pcmcia stuff */\n-\tpcmcia_disable_device(pcmcia);\n-}\n-\n-/*\n- * platform_device wrapper\n- * pdev-\u003eresource has 2 entries: io \u0026 irq\n- */\n-static void softingcs_pdev_release(struct device *dev)\n-{\n-\tstruct platform_device *pdev = to_platform_device(dev);\n-\tkfree(pdev);\n-}\n-\n-static int softingcs_probe(struct pcmcia_device *pcmcia)\n-{\n-\tint ret;\n-\tstruct platform_device *pdev;\n-\tconst struct softing_platform_data *pdat;\n-\tstruct resource *pres;\n-\tstruct dev {\n-\t\tstruct platform_device pdev;\n-\t\tstruct resource res[2];\n-\t} *dev;\n-\n-\t/* find matching platform_data */\n-\tpdat = softingcs_find_platform_data(pcmcia-\u003emanf_id, pcmcia-\u003ecard_id);\n-\tif (!pdat)\n-\t\treturn -ENOTTY;\n-\n-\t/* setup pcmcia device */\n-\tpcmcia-\u003econfig_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |\n-\t\tCONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;\n-\tret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);\n-\tif (ret)\n-\t\tgoto pcmcia_failed;\n-\n-\tret = pcmcia_enable_device(pcmcia);\n-\tif (ret \u003c 0)\n-\t\tgoto pcmcia_failed;\n-\n-\tpres = pcmcia-\u003eresource[PCMCIA_IOMEM_0];\n-\tif (!pres) {\n-\t\tret = -EBADF;\n-\t\tgoto pcmcia_bad;\n-\t}\n-\n-\t/* create softing platform device */\n-\tdev = kzalloc_obj(*dev);\n-\tif (!dev) {\n-\t\tret = -ENOMEM;\n-\t\tgoto mem_failed;\n-\t}\n-\tdev-\u003epdev.resource = dev-\u003eres;\n-\tdev-\u003epdev.num_resources = ARRAY_SIZE(dev-\u003eres);\n-\tdev-\u003epdev.dev.release = softingcs_pdev_release;\n-\n-\tpdev = \u0026dev-\u003epdev;\n-\tpdev-\u003edev.platform_data = (void *)pdat;\n-\tpdev-\u003edev.parent = \u0026pcmcia-\u003edev;\n-\tpcmcia-\u003epriv = pdev;\n-\n-\t/* platform device resources */\n-\tpdev-\u003eresource[0].flags = IORESOURCE_MEM;\n-\tpdev-\u003eresource[0].start = pres-\u003estart;\n-\tpdev-\u003eresource[0].end = pres-\u003eend;\n-\n-\tpdev-\u003eresource[1].flags = IORESOURCE_IRQ;\n-\tpdev-\u003eresource[1].start = pcmcia-\u003eirq;\n-\tpdev-\u003eresource[1].end = pdev-\u003eresource[1].start;\n-\n-\t/* platform device setup */\n-\tspin_lock(\u0026softingcs_index_lock);\n-\tpdev-\u003eid = softingcs_index++;\n-\tspin_unlock(\u0026softingcs_index_lock);\n-\tpdev-\u003ename = \"softing\";\n-\tdev_set_name(\u0026pdev-\u003edev, \"softingcs.%i\", pdev-\u003eid);\n-\tret = platform_device_register(pdev);\n-\tif (ret \u003c 0)\n-\t\tgoto platform_failed;\n-\n-\tdev_info(\u0026pcmcia-\u003edev, \"created %s\\n\", dev_name(\u0026pdev-\u003edev));\n-\treturn 0;\n-\n-platform_failed:\n-\tplatform_device_put(pdev);\n-mem_failed:\n-pcmcia_bad:\n-pcmcia_failed:\n-\tpcmcia_disable_device(pcmcia);\n-\tpcmcia-\u003epriv = NULL;\n-\treturn ret;\n-}\n-\n-static const struct pcmcia_device_id softingcs_ids[] = {\n-\t/* softing */\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),\n-\t/* vector, manufacturer? */\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),\n-\t/* EDIC */\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),\n-\tPCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),\n-\tPCMCIA_DEVICE_NULL,\n-};\n-\n-MODULE_DEVICE_TABLE(pcmcia, softingcs_ids);\n-\n-static struct pcmcia_driver softingcs_driver = {\n-\t.owner\t\t= THIS_MODULE,\n-\t.name\t\t= \"softingcs\",\n-\t.id_table\t= softingcs_ids,\n-\t.probe\t\t= softingcs_probe,\n-\t.remove\t\t= softingcs_remove,\n-};\n-\n-module_pcmcia_driver(softingcs_driver);\n-\n-MODULE_DESCRIPTION(\"softing CANcard driver\"\n-\t\t\", links PCMCIA card to softing driver\");\n-MODULE_LICENSE(\"GPL v2\");\ndiff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c\ndeleted file mode 100644\nindex 282570daf3efe..0000000000000\n--- a/drivers/net/can/softing/softing_fw.c\n+++ /dev/null\n@@ -1,700 +0,0 @@\n-// SPDX-License-Identifier: GPL-2.0-only\n-/*\n- * Copyright (C) 2008-2010\n- *\n- * - Kurt Van Dijck, EIA Electronics\n- */\n-\n-#include \u003clinux/firmware.h\u003e\n-#include \u003clinux/sched/signal.h\u003e\n-#include \u003casm/div64.h\u003e\n-#include \u003casm/io.h\u003e\n-\n-#include \"softing.h\"\n-\n-/*\n- * low level DPRAM command.\n- * Make sure that card-\u003edpram[DPRAM_FCT_HOST] is preset\n- */\n-static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector,\n-\t\tconst char *msg)\n-{\n-\tint ret;\n-\tunsigned long stamp;\n-\n-\tiowrite16(cmd, \u0026card-\u003edpram[DPRAM_FCT_PARAM]);\n-\tiowrite8(vector \u003e\u003e 8, \u0026card-\u003edpram[DPRAM_FCT_HOST + 1]);\n-\tiowrite8(vector, \u0026card-\u003edpram[DPRAM_FCT_HOST]);\n-\t/* be sure to flush this to the card */\n-\twmb();\n-\tstamp = jiffies + 1 * HZ;\n-\t/* wait for card */\n-\tdo {\n-\t\t/* DPRAM_FCT_HOST is _not_ aligned */\n-\t\tret = ioread8(\u0026card-\u003edpram[DPRAM_FCT_HOST]) +\n-\t\t\t(ioread8(\u0026card-\u003edpram[DPRAM_FCT_HOST + 1]) \u003c\u003c 8);\n-\t\t/* don't have any cached variables */\n-\t\trmb();\n-\t\tif (ret == RES_OK)\n-\t\t\t/* read return-value now */\n-\t\t\treturn ioread16(\u0026card-\u003edpram[DPRAM_FCT_RESULT]);\n-\n-\t\tif ((ret != vector) || time_after(jiffies, stamp))\n-\t\t\tbreak;\n-\t\t/* process context =\u003e relax */\n-\t\tusleep_range(500, 10000);\n-\t} while (1);\n-\n-\tret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;\n-\tdev_alert(\u0026card-\u003epdev-\u003edev, \"firmware %s failed (%i)\\n\", msg, ret);\n-\treturn ret;\n-}\n-\n-static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg)\n-{\n-\tint ret;\n-\n-\tret = _softing_fct_cmd(card, cmd, 0, msg);\n-\tif (ret \u003e 0) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"%s returned %u\\n\", msg, ret);\n-\t\tret = -EIO;\n-\t}\n-\treturn ret;\n-}\n-\n-int softing_bootloader_command(struct softing *card, int16_t cmd,\n-\t\tconst char *msg)\n-{\n-\tint ret;\n-\tunsigned long stamp;\n-\n-\tiowrite16(RES_NONE, \u0026card-\u003edpram[DPRAM_RECEIPT]);\n-\tiowrite16(cmd, \u0026card-\u003edpram[DPRAM_COMMAND]);\n-\t/* be sure to flush this to the card */\n-\twmb();\n-\tstamp = jiffies + 3 * HZ;\n-\t/* wait for card */\n-\tdo {\n-\t\tret = ioread16(\u0026card-\u003edpram[DPRAM_RECEIPT]);\n-\t\t/* don't have any cached variables */\n-\t\trmb();\n-\t\tif (ret == RES_OK)\n-\t\t\treturn 0;\n-\t\tif (time_after(jiffies, stamp))\n-\t\t\tbreak;\n-\t\t/* process context =\u003e relax */\n-\t\tusleep_range(500, 10000);\n-\t} while (!signal_pending(current));\n-\n-\tret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;\n-\tdev_alert(\u0026card-\u003epdev-\u003edev, \"bootloader %s failed (%i)\\n\", msg, ret);\n-\treturn ret;\n-}\n-\n-static int fw_parse(const u8 **pmem, const u8 *limit, u16 *ptype,\n-\t\t    u32 *paddr, u16 *plen, const u8 **pdat)\n-{\n-\tuint16_t checksum[2];\n-\tconst u8 *mem;\n-\tconst u8 *record_end;\n-\n-\t/*\n-\t * firmware records are a binary, unaligned stream composed of:\n-\t * uint16_t type;\n-\t * uint32_t addr;\n-\t * uint16_t len;\n-\t * uint8_t dat[len];\n-\t * uint16_t checksum;\n-\t * all values in little endian.\n-\t * We could define a struct for this, with __attribute__((packed)),\n-\t * but would that solve the alignment in _all_ cases (cfr. the\n-\t * struct itself may be an odd address)?\n-\t *\n-\t * I chose to use leXX_to_cpup() since this solves both\n-\t * endianness \u0026 alignment.\n-\t */\n-\tmem = *pmem;\n-\t/* A record needs an 8-byte prefix and a 2-byte checksum. */\n-\tif (mem \u003e limit || limit - mem \u003c 10)\n-\t\treturn -EINVAL;\n-\n-\t*ptype = le16_to_cpup((void *)\u0026mem[0]);\n-\t*paddr = le32_to_cpup((void *)\u0026mem[2]);\n-\t*plen = le16_to_cpup((void *)\u0026mem[6]);\n-\tif (*plen \u003e limit - mem - 10)\n-\t\treturn -EINVAL;\n-\n-\t*pdat = \u0026mem[8];\n-\t/* verify checksum */\n-\trecord_end = \u0026mem[8 + *plen];\n-\tchecksum[0] = le16_to_cpup((void *)record_end);\n-\tfor (checksum[1] = 0; mem \u003c record_end; ++mem)\n-\t\tchecksum[1] += *mem;\n-\tif (checksum[0] != checksum[1])\n-\t\treturn -EINVAL;\n-\t/* increment */\n-\t*pmem += 10 + *plen;\n-\treturn 0;\n-}\n-\n-int softing_load_fw(const char *file, struct softing *card,\n-\t\t__iomem uint8_t *dpram, unsigned int size, int offset)\n-{\n-\tconst struct firmware *fw;\n-\tint ret;\n-\tconst uint8_t *mem, *end, *dat;\n-\tuint16_t type, len;\n-\tuint32_t addr;\n-\tuint8_t *buf = NULL, *new_buf;\n-\ts64 dpram_offset;\n-\tint buflen = 0;\n-\tint8_t type_end = 0;\n-\n-\tret = request_firmware(\u0026fw, file, \u0026card-\u003epdev-\u003edev);\n-\tif (ret \u003c 0)\n-\t\treturn ret;\n-\tdev_dbg(\u0026card-\u003epdev-\u003edev, \"%s, firmware(%s) got %u bytes\"\n-\t\t\", offset %c0x%04x\\n\",\n-\t\tcard-\u003epdat-\u003ename, file, (unsigned int)fw-\u003esize,\n-\t\t(offset \u003e= 0) ? '+' : '-', (unsigned int)abs(offset));\n-\t/* parse the firmware */\n-\tmem = fw-\u003edata;\n-\tend = \u0026mem[fw-\u003esize];\n-\t/* look for header record */\n-\tret = fw_parse(\u0026mem, end, \u0026type, \u0026addr, \u0026len, \u0026dat);\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\tif (type != 0xffff)\n-\t\tgoto failed;\n-\tif (strncmp(\"Structured Binary Format, Softing GmbH\" , dat, len)) {\n-\t\tret = -EINVAL;\n-\t\tgoto failed;\n-\t}\n-\t/* ok, we had a header */\n-\twhile (mem \u003c end) {\n-\t\tret = fw_parse(\u0026mem, end, \u0026type, \u0026addr, \u0026len, \u0026dat);\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\tif (type == 3) {\n-\t\t\t/* start address, not used here */\n-\t\t\tcontinue;\n-\t\t} else if (type == 1) {\n-\t\t\t/* eof */\n-\t\t\ttype_end = 1;\n-\t\t\tbreak;\n-\t\t} else if (type != 0) {\n-\t\t\tret = -EINVAL;\n-\t\t\tgoto failed;\n-\t\t}\n-\n-\t\tdpram_offset = (s64)addr + offset;\n-\t\tif (dpram_offset \u003c 0 || dpram_offset \u003e size ||\n-\t\t    len \u003e size - dpram_offset) {\n-\t\t\tret = -EINVAL;\n-\t\t\tgoto failed;\n-\t\t}\n-\t\tmemcpy_toio(\u0026dpram[dpram_offset], dat, len);\n-\t\t/* be sure to flush caches from IO space */\n-\t\tmb();\n-\t\tif (len \u003e buflen) {\n-\t\t\t/* align buflen */\n-\t\t\tbuflen = (len + (1024-1)) \u0026 ~(1024-1);\n-\t\t\tnew_buf = krealloc(buf, buflen, GFP_KERNEL);\n-\t\t\tif (!new_buf) {\n-\t\t\t\tret = -ENOMEM;\n-\t\t\t\tgoto failed;\n-\t\t\t}\n-\t\t\tbuf = new_buf;\n-\t\t}\n-\t\t/* verify record data */\n-\t\tmemcpy_fromio(buf, \u0026dpram[dpram_offset], len);\n-\t\tif (memcmp(buf, dat, len)) {\n-\t\t\t/* is not ok */\n-\t\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"DPRAM readback failed\\n\");\n-\t\t\tret = -EIO;\n-\t\t\tgoto failed;\n-\t\t}\n-\t}\n-\tif (!type_end)\n-\t\t/* no end record seen */\n-\t\tgoto failed;\n-\tret = 0;\n-failed:\n-\tkfree(buf);\n-\trelease_firmware(fw);\n-\tif (ret \u003c 0)\n-\t\tdev_info(\u0026card-\u003epdev-\u003edev, \"firmware %s failed\\n\", file);\n-\treturn ret;\n-}\n-\n-int softing_load_app_fw(const char *file, struct softing *card)\n-{\n-\tconst struct firmware *fw;\n-\tconst uint8_t *mem, *end, *dat;\n-\tint ret, j;\n-\tuint16_t type, len;\n-\tuint32_t addr, start_addr = 0;\n-\tunsigned int sum, rx_sum;\n-\tint8_t type_end = 0, type_entrypoint = 0;\n-\n-\tret = request_firmware(\u0026fw, file, \u0026card-\u003epdev-\u003edev);\n-\tif (ret) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"request_firmware(%s) got %i\\n\",\n-\t\t\tfile, ret);\n-\t\treturn ret;\n-\t}\n-\tdev_dbg(\u0026card-\u003epdev-\u003edev, \"firmware(%s) got %lu bytes\\n\",\n-\t\tfile, (unsigned long)fw-\u003esize);\n-\t/* parse the firmware */\n-\tmem = fw-\u003edata;\n-\tend = \u0026mem[fw-\u003esize];\n-\t/* look for header record */\n-\tret = fw_parse(\u0026mem, end, \u0026type, \u0026addr, \u0026len, \u0026dat);\n-\tif (ret)\n-\t\tgoto failed;\n-\tret = -EINVAL;\n-\tif (type != 0xffff) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"firmware starts with type 0x%x\\n\",\n-\t\t\ttype);\n-\t\tgoto failed;\n-\t}\n-\tif (strncmp(\"Structured Binary Format, Softing GmbH\", dat, len)) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"firmware string '%.*s' fault\\n\",\n-\t\t\t\tlen, dat);\n-\t\tgoto failed;\n-\t}\n-\t/* ok, we had a header */\n-\twhile (mem \u003c end) {\n-\t\tret = fw_parse(\u0026mem, end, \u0026type, \u0026addr, \u0026len, \u0026dat);\n-\t\tif (ret)\n-\t\t\tgoto failed;\n-\n-\t\tif (type == 3) {\n-\t\t\t/* start address */\n-\t\t\tstart_addr = addr;\n-\t\t\ttype_entrypoint = 1;\n-\t\t\tcontinue;\n-\t\t} else if (type == 1) {\n-\t\t\t/* eof */\n-\t\t\ttype_end = 1;\n-\t\t\tbreak;\n-\t\t} else if (type != 0) {\n-\t\t\tdev_alert(\u0026card-\u003epdev-\u003edev,\n-\t\t\t\t\t\"unknown record type 0x%04x\\n\", type);\n-\t\t\tret = -EINVAL;\n-\t\t\tgoto failed;\n-\t\t}\n-\n-\t\t/* regular data */\n-\t\tfor (sum = 0, j = 0; j \u003c len; ++j)\n-\t\t\tsum += dat[j];\n-\t\t/* work in 16bit (target) */\n-\t\tsum \u0026= 0xffff;\n-\n-\t\tif (card-\u003epdat-\u003eapp.offs \u003e card-\u003edpram_size ||\n-\t\t    len \u003e card-\u003edpram_size - card-\u003epdat-\u003eapp.offs) {\n-\t\t\tret = -EINVAL;\n-\t\t\tgoto failed;\n-\t\t}\n-\n-\t\tmemcpy_toio(\u0026card-\u003edpram[card-\u003epdat-\u003eapp.offs], dat, len);\n-\t\tiowrite32(card-\u003epdat-\u003eapp.offs + card-\u003epdat-\u003eapp.addr,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_COMMAND + 2]);\n-\t\tiowrite32(addr, \u0026card-\u003edpram[DPRAM_COMMAND + 6]);\n-\t\tiowrite16(len, \u0026card-\u003edpram[DPRAM_COMMAND + 10]);\n-\t\tiowrite8(1, \u0026card-\u003edpram[DPRAM_COMMAND + 12]);\n-\t\tret = softing_bootloader_command(card, 1, \"loading app.\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* verify checksum */\n-\t\trx_sum = ioread16(\u0026card-\u003edpram[DPRAM_RECEIPT + 2]);\n-\t\tif (rx_sum != sum) {\n-\t\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"SRAM seems to be damaged\"\n-\t\t\t\t\", wanted 0x%04x, got 0x%04x\\n\", sum, rx_sum);\n-\t\t\tret = -EIO;\n-\t\t\tgoto failed;\n-\t\t}\n-\t}\n-\tif (!type_end || !type_entrypoint)\n-\t\tgoto failed;\n-\t/* start application in card */\n-\tiowrite32(start_addr, \u0026card-\u003edpram[DPRAM_COMMAND + 2]);\n-\tiowrite8(1, \u0026card-\u003edpram[DPRAM_COMMAND + 6]);\n-\tret = softing_bootloader_command(card, 3, \"start app.\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\tret = 0;\n-failed:\n-\trelease_firmware(fw);\n-\tif (ret \u003c 0)\n-\t\tdev_info(\u0026card-\u003epdev-\u003edev, \"firmware %s failed\\n\", file);\n-\treturn ret;\n-}\n-\n-static int softing_reset_chip(struct softing *card)\n-{\n-\tint ret;\n-\n-\tdo {\n-\t\t/* reset chip */\n-\t\tiowrite8(0, \u0026card-\u003edpram[DPRAM_RESET_RX_FIFO]);\n-\t\tiowrite8(0, \u0026card-\u003edpram[DPRAM_RESET_RX_FIFO+1]);\n-\t\tiowrite8(1, \u0026card-\u003edpram[DPRAM_RESET]);\n-\t\tiowrite8(0, \u0026card-\u003edpram[DPRAM_RESET+1]);\n-\n-\t\tret = softing_fct_cmd(card, 0, \"reset_can\");\n-\t\tif (!ret)\n-\t\t\tbreak;\n-\t\tif (signal_pending(current))\n-\t\t\t/* don't wait any longer */\n-\t\t\tbreak;\n-\t} while (1);\n-\tcard-\u003etx.pending = 0;\n-\treturn ret;\n-}\n-\n-int softing_chip_poweron(struct softing *card)\n-{\n-\tint ret;\n-\t/* sync */\n-\tret = _softing_fct_cmd(card, 99, 0x55, \"sync-a\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\n-\tret = _softing_fct_cmd(card, 99, 0xaa, \"sync-b\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\n-\tret = softing_reset_chip(card);\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\t/* get_serial */\n-\tret = softing_fct_cmd(card, 43, \"get_serial_number\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\tcard-\u003eid.serial = ioread32(\u0026card-\u003edpram[DPRAM_FCT_PARAM]);\n-\t/* get_version */\n-\tret = softing_fct_cmd(card, 12, \"get_version\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\tcard-\u003eid.fw_version = ioread16(\u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\tcard-\u003eid.hw_version = ioread16(\u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\tcard-\u003eid.license = ioread16(\u0026card-\u003edpram[DPRAM_FCT_PARAM + 6]);\n-\tcard-\u003eid.chip[0] = ioread16(\u0026card-\u003edpram[DPRAM_FCT_PARAM + 8]);\n-\tcard-\u003eid.chip[1] = ioread16(\u0026card-\u003edpram[DPRAM_FCT_PARAM + 10]);\n-\treturn 0;\n-failed:\n-\treturn ret;\n-}\n-\n-static void softing_initialize_timestamp(struct softing *card)\n-{\n-\tuint64_t ovf;\n-\n-\tcard-\u003ets_ref = ktime_get();\n-\n-\t/* 16MHz is the reference */\n-\tovf = 0x100000000ULL * 16;\n-\tdo_div(ovf, card-\u003epdat-\u003efreq ?: 16);\n-\n-\tcard-\u003ets_overflow = ktime_add_us(0, ovf);\n-}\n-\n-ktime_t softing_raw2ktime(struct softing *card, u32 raw)\n-{\n-\tuint64_t rawl;\n-\tktime_t now, real_offset;\n-\tktime_t target;\n-\tktime_t tmp;\n-\n-\tnow = ktime_get();\n-\treal_offset = ktime_sub(ktime_get_real(), now);\n-\n-\t/* find nsec from card */\n-\trawl = raw * 16;\n-\tdo_div(rawl, card-\u003epdat-\u003efreq ?: 16);\n-\ttarget = ktime_add_us(card-\u003ets_ref, rawl);\n-\t/* test for overflows */\n-\ttmp = ktime_add(target, card-\u003ets_overflow);\n-\twhile (unlikely(ktime_to_ns(tmp) \u003e ktime_to_ns(now))) {\n-\t\tcard-\u003ets_ref = ktime_add(card-\u003ets_ref, card-\u003ets_overflow);\n-\t\ttarget = tmp;\n-\t\ttmp = ktime_add(target, card-\u003ets_overflow);\n-\t}\n-\treturn ktime_add(target, real_offset);\n-}\n-\n-static inline int softing_error_reporting(struct net_device *netdev)\n-{\n-\tstruct softing_priv *priv = netdev_priv(netdev);\n-\n-\treturn (priv-\u003ecan.ctrlmode \u0026 CAN_CTRLMODE_BERR_REPORTING)\n-\t\t? 1 : 0;\n-}\n-\n-int softing_startstop(struct net_device *dev, int up)\n-{\n-\tint ret;\n-\tstruct softing *card;\n-\tstruct softing_priv *priv;\n-\tstruct net_device *netdev;\n-\tint bus_bitmask_start;\n-\tint j, error_reporting;\n-\tstruct can_frame msg;\n-\tconst struct can_bittiming *bt;\n-\n-\tpriv = netdev_priv(dev);\n-\tcard = priv-\u003ecard;\n-\n-\tif (!card-\u003efw.up)\n-\t\treturn -EIO;\n-\n-\tret = mutex_lock_interruptible(\u0026card-\u003efw.lock);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tbus_bitmask_start = 0;\n-\tif (up)\n-\t\t/* prepare to start this bus as well */\n-\t\tbus_bitmask_start |= (1 \u003c\u003c priv-\u003eindex);\n-\t/* bring netdevs down */\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tnetdev = card-\u003enet[j];\n-\t\tif (!netdev)\n-\t\t\tcontinue;\n-\t\tpriv = netdev_priv(netdev);\n-\n-\t\tif (dev != netdev)\n-\t\t\tnetif_stop_queue(netdev);\n-\n-\t\tif (netif_running(netdev)) {\n-\t\t\tif (dev != netdev)\n-\t\t\t\tbus_bitmask_start |= (1 \u003c\u003c j);\n-\t\t\tpriv-\u003etx.pending = 0;\n-\t\t\tpriv-\u003etx.echo_put = 0;\n-\t\t\tpriv-\u003etx.echo_get = 0;\n-\t\t\t/*\n-\t\t\t * this bus' may just have called open_candev()\n-\t\t\t * which is rather stupid to call close_candev()\n-\t\t\t * already\n-\t\t\t * but we may come here from busoff recovery too\n-\t\t\t * in which case the echo_skb _needs_ flushing too.\n-\t\t\t * just be sure to call open_candev() again\n-\t\t\t */\n-\t\t\tclose_candev(netdev);\n-\t\t}\n-\t\tpriv-\u003ecan.state = CAN_STATE_STOPPED;\n-\t}\n-\tcard-\u003etx.pending = 0;\n-\n-\tsofting_enable_irq(card, 0);\n-\tret = softing_reset_chip(card);\n-\tif (ret)\n-\t\tgoto failed;\n-\tif (!bus_bitmask_start)\n-\t\t/* no buses to be brought up */\n-\t\tgoto card_done;\n-\n-\tif ((bus_bitmask_start \u0026 1) \u0026\u0026 (bus_bitmask_start \u0026 2)\n-\t\t\t\u0026\u0026 (softing_error_reporting(card-\u003enet[0])\n-\t\t\t\t!= softing_error_reporting(card-\u003enet[1]))) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev,\n-\t\t\t\t\"err_reporting flag differs for buses\\n\");\n-\t\tgoto invalid;\n-\t}\n-\terror_reporting = 0;\n-\tif (bus_bitmask_start \u0026 1) {\n-\t\tnetdev = card-\u003enet[0];\n-\t\tpriv = netdev_priv(netdev);\n-\t\terror_reporting += softing_error_reporting(netdev);\n-\t\t/* init chip 1 */\n-\t\tbt = \u0026priv-\u003ecan.bittiming;\n-\t\tiowrite16(bt-\u003ebrp, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tiowrite16(bt-\u003esjw, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\t\tiowrite16(bt-\u003ephase_seg1 + bt-\u003eprop_seg,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_FCT_PARAM + 6]);\n-\t\tiowrite16(bt-\u003ephase_seg2, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 8]);\n-\t\tiowrite16((priv-\u003ecan.ctrlmode \u0026 CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_FCT_PARAM + 10]);\n-\t\tret = softing_fct_cmd(card, 1, \"initialize_chip[0]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* set mode */\n-\t\tiowrite16(0, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tiowrite16(0, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\t\tret = softing_fct_cmd(card, 3, \"set_mode[0]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* set filter */\n-\t\t/* 11bit id \u0026 mask */\n-\t\tiowrite16(0x0000, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tiowrite16(0x07ff, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\t\t/* 29bit id.lo \u0026 mask.lo \u0026 id.hi \u0026 mask.hi */\n-\t\tiowrite16(0x0000, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 6]);\n-\t\tiowrite16(0xffff, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 8]);\n-\t\tiowrite16(0x0000, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 10]);\n-\t\tiowrite16(0x1fff, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 12]);\n-\t\tret = softing_fct_cmd(card, 7, \"set_filter[0]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* set output control */\n-\t\tiowrite16(priv-\u003eoutput, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tret = softing_fct_cmd(card, 5, \"set_output[0]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t}\n-\tif (bus_bitmask_start \u0026 2) {\n-\t\tnetdev = card-\u003enet[1];\n-\t\tpriv = netdev_priv(netdev);\n-\t\terror_reporting += softing_error_reporting(netdev);\n-\t\t/* init chip2 */\n-\t\tbt = \u0026priv-\u003ecan.bittiming;\n-\t\tiowrite16(bt-\u003ebrp, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tiowrite16(bt-\u003esjw, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\t\tiowrite16(bt-\u003ephase_seg1 + bt-\u003eprop_seg,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_FCT_PARAM + 6]);\n-\t\tiowrite16(bt-\u003ephase_seg2, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 8]);\n-\t\tiowrite16((priv-\u003ecan.ctrlmode \u0026 CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_FCT_PARAM + 10]);\n-\t\tret = softing_fct_cmd(card, 2, \"initialize_chip[1]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* set mode2 */\n-\t\tiowrite16(0, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tiowrite16(0, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\t\tret = softing_fct_cmd(card, 4, \"set_mode[1]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* set filter2 */\n-\t\t/* 11bit id \u0026 mask */\n-\t\tiowrite16(0x0000, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tiowrite16(0x07ff, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\t\t/* 29bit id.lo \u0026 mask.lo \u0026 id.hi \u0026 mask.hi */\n-\t\tiowrite16(0x0000, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 6]);\n-\t\tiowrite16(0xffff, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 8]);\n-\t\tiowrite16(0x0000, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 10]);\n-\t\tiowrite16(0x1fff, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 12]);\n-\t\tret = softing_fct_cmd(card, 8, \"set_filter[1]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t\t/* set output control2 */\n-\t\tiowrite16(priv-\u003eoutput, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\t\tret = softing_fct_cmd(card, 6, \"set_output[1]\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t}\n-\n-\t/* enable_error_frame\n-\t *\n-\t * Error reporting is switched off at the moment since\n-\t * the receiving of them is not yet 100% verified\n-\t * This should be enabled sooner or later\n-\t */\n-\tif (0 \u0026\u0026 error_reporting) {\n-\t\tret = softing_fct_cmd(card, 51, \"enable_error_frame\");\n-\t\tif (ret \u003c 0)\n-\t\t\tgoto failed;\n-\t}\n-\n-\t/* initialize interface */\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 2]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 4]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 6]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 8]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 10]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 12]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 14]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 16]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 18]);\n-\tiowrite16(1, \u0026card-\u003edpram[DPRAM_FCT_PARAM + 20]);\n-\tret = softing_fct_cmd(card, 17, \"initialize_interface\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\t/* enable_fifo */\n-\tret = softing_fct_cmd(card, 36, \"enable_fifo\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\t/* enable fifo tx ack */\n-\tret = softing_fct_cmd(card, 13, \"fifo_tx_ack[0]\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\t/* enable fifo tx ack2 */\n-\tret = softing_fct_cmd(card, 14, \"fifo_tx_ack[1]\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\t/* start_chip */\n-\tret = softing_fct_cmd(card, 11, \"start_chip\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\tiowrite8(0, \u0026card-\u003edpram[DPRAM_INFO_BUSSTATE]);\n-\tiowrite8(0, \u0026card-\u003edpram[DPRAM_INFO_BUSSTATE2]);\n-\tif (card-\u003epdat-\u003egeneration \u003c 2) {\n-\t\tiowrite8(0, \u0026card-\u003edpram[DPRAM_V2_IRQ_TOHOST]);\n-\t\t/* flush the DPRAM caches */\n-\t\twmb();\n-\t}\n-\n-\tsofting_initialize_timestamp(card);\n-\n-\t/*\n-\t * do socketcan notifications/status changes\n-\t * from here, no errors should occur, or the failed: part\n-\t * must be reviewed\n-\t */\n-\tmemset(\u0026msg, 0, sizeof(msg));\n-\tmsg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;\n-\tmsg.len = CAN_ERR_DLC;\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tif (!(bus_bitmask_start \u0026 (1 \u003c\u003c j)))\n-\t\t\tcontinue;\n-\t\tnetdev = card-\u003enet[j];\n-\t\tif (!netdev)\n-\t\t\tcontinue;\n-\t\tpriv = netdev_priv(netdev);\n-\t\tpriv-\u003ecan.state = CAN_STATE_ERROR_ACTIVE;\n-\t\topen_candev(netdev);\n-\t\tif (dev != netdev) {\n-\t\t\t/* notify other buses on the restart */\n-\t\t\tsofting_netdev_rx(netdev, \u0026msg, 0);\n-\t\t\t++priv-\u003ecan.can_stats.restarts;\n-\t\t}\n-\t\tnetif_wake_queue(netdev);\n-\t}\n-\n-\t/* enable interrupts */\n-\tret = softing_enable_irq(card, 1);\n-\tif (ret)\n-\t\tgoto failed;\n-card_done:\n-\tmutex_unlock(\u0026card-\u003efw.lock);\n-\treturn 0;\n-invalid:\n-\tret = -EINVAL;\n-failed:\n-\tsofting_enable_irq(card, 0);\n-\tsofting_reset_chip(card);\n-\tmutex_unlock(\u0026card-\u003efw.lock);\n-\t/* bring all other interfaces down */\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tnetdev = card-\u003enet[j];\n-\t\tif (!netdev)\n-\t\t\tcontinue;\n-\t\tdev_close(netdev);\n-\t}\n-\treturn ret;\n-}\n-\n-int softing_default_output(struct net_device *netdev)\n-{\n-\tstruct softing_priv *priv = netdev_priv(netdev);\n-\tstruct softing *card = priv-\u003ecard;\n-\n-\tswitch (priv-\u003echip) {\n-\tcase 1000:\n-\t\treturn (card-\u003epdat-\u003egeneration \u003c 2) ? 0xfb : 0xfa;\n-\tcase 5:\n-\t\treturn 0x60;\n-\tdefault:\n-\t\treturn 0x40;\n-\t}\n-}\ndiff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c\ndeleted file mode 100644\nindex 519ab3097f866..0000000000000\n--- a/drivers/net/can/softing/softing_main.c\n+++ /dev/null\n@@ -1,864 +0,0 @@\n-// SPDX-License-Identifier: GPL-2.0-only\n-/*\n- * Copyright (C) 2008-2010\n- *\n- * - Kurt Van Dijck, EIA Electronics\n- */\n-\n-#include \u003clinux/ethtool.h\u003e\n-#include \u003clinux/module.h\u003e\n-#include \u003clinux/interrupt.h\u003e\n-#include \u003casm/io.h\u003e\n-\n-#include \"softing.h\"\n-\n-#define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1)\n-\n-/*\n- * test is a specific CAN netdev\n- * is online (ie. up 'n running, not sleeping, not busoff\n- */\n-static inline int canif_is_active(struct net_device *netdev)\n-{\n-\tstruct can_priv *can = netdev_priv(netdev);\n-\n-\tif (!netif_running(netdev))\n-\t\treturn 0;\n-\treturn (can-\u003estate \u003c= CAN_STATE_ERROR_PASSIVE);\n-}\n-\n-/* reset DPRAM */\n-static inline void softing_set_reset_dpram(struct softing *card)\n-{\n-\tif (card-\u003epdat-\u003egeneration \u003e= 2) {\n-\t\tspin_lock_bh(\u0026card-\u003espin);\n-\t\tiowrite8(ioread8(\u0026card-\u003edpram[DPRAM_V2_RESET]) \u0026 ~1,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_V2_RESET]);\n-\t\tspin_unlock_bh(\u0026card-\u003espin);\n-\t}\n-}\n-\n-static inline void softing_clr_reset_dpram(struct softing *card)\n-{\n-\tif (card-\u003epdat-\u003egeneration \u003e= 2) {\n-\t\tspin_lock_bh(\u0026card-\u003espin);\n-\t\tiowrite8(ioread8(\u0026card-\u003edpram[DPRAM_V2_RESET]) | 1,\n-\t\t\t\t\u0026card-\u003edpram[DPRAM_V2_RESET]);\n-\t\tspin_unlock_bh(\u0026card-\u003espin);\n-\t}\n-}\n-\n-/* trigger the tx queue-ing */\n-static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,\n-\t\tstruct net_device *dev)\n-{\n-\tstruct softing_priv *priv = netdev_priv(dev);\n-\tstruct softing *card = priv-\u003ecard;\n-\tint ret;\n-\tuint8_t *ptr;\n-\tuint8_t fifo_wr, fifo_rd;\n-\tstruct can_frame *cf = (struct can_frame *)skb-\u003edata;\n-\tuint8_t buf[DPRAM_TX_SIZE];\n-\n-\tif (can_dev_dropped_skb(dev, skb))\n-\t\treturn NETDEV_TX_OK;\n-\n-\tspin_lock(\u0026card-\u003espin);\n-\n-\tret = NETDEV_TX_BUSY;\n-\tif (!card-\u003efw.up ||\n-\t\t\t(card-\u003etx.pending \u003e= TXMAX) ||\n-\t\t\t(priv-\u003etx.pending \u003e= TX_ECHO_SKB_MAX))\n-\t\tgoto xmit_done;\n-\tfifo_wr = ioread8(\u0026card-\u003edpram[DPRAM_TX_WR]);\n-\tfifo_rd = ioread8(\u0026card-\u003edpram[DPRAM_TX_RD]);\n-\tif (fifo_wr == fifo_rd)\n-\t\t/* fifo full */\n-\t\tgoto xmit_done;\n-\tmemset(buf, 0, sizeof(buf));\n-\tptr = buf;\n-\t*ptr = CMD_TX;\n-\tif (cf-\u003ecan_id \u0026 CAN_RTR_FLAG)\n-\t\t*ptr |= CMD_RTR;\n-\tif (cf-\u003ecan_id \u0026 CAN_EFF_FLAG)\n-\t\t*ptr |= CMD_XTD;\n-\tif (priv-\u003eindex)\n-\t\t*ptr |= CMD_BUS2;\n-\t++ptr;\n-\t*ptr++ = cf-\u003elen;\n-\t*ptr++ = (cf-\u003ecan_id \u003e\u003e 0);\n-\t*ptr++ = (cf-\u003ecan_id \u003e\u003e 8);\n-\tif (cf-\u003ecan_id \u0026 CAN_EFF_FLAG) {\n-\t\t*ptr++ = (cf-\u003ecan_id \u003e\u003e 16);\n-\t\t*ptr++ = (cf-\u003ecan_id \u003e\u003e 24);\n-\t} else {\n-\t\t/* increment 1, not 2 as you might think */\n-\t\tptr += 1;\n-\t}\n-\tif (!(cf-\u003ecan_id \u0026 CAN_RTR_FLAG))\n-\t\tmemcpy(ptr, \u0026cf-\u003edata[0], cf-\u003elen);\n-\tmemcpy_toio(\u0026card-\u003edpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr],\n-\t\t\tbuf, DPRAM_TX_SIZE);\n-\tif (++fifo_wr \u003e= DPRAM_TX_CNT)\n-\t\tfifo_wr = 0;\n-\tiowrite8(fifo_wr, \u0026card-\u003edpram[DPRAM_TX_WR]);\n-\tcard-\u003etx.last_bus = priv-\u003eindex;\n-\t++card-\u003etx.pending;\n-\t++priv-\u003etx.pending;\n-\tcan_put_echo_skb(skb, dev, priv-\u003etx.echo_put, 0);\n-\t++priv-\u003etx.echo_put;\n-\tif (priv-\u003etx.echo_put \u003e= TX_ECHO_SKB_MAX)\n-\t\tpriv-\u003etx.echo_put = 0;\n-\t/* can_put_echo_skb() saves the skb, safe to return TX_OK */\n-\tret = NETDEV_TX_OK;\n-xmit_done:\n-\tspin_unlock(\u0026card-\u003espin);\n-\tif (card-\u003etx.pending \u003e= TXMAX) {\n-\t\tint j;\n-\t\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\t\tif (card-\u003enet[j])\n-\t\t\t\tnetif_stop_queue(card-\u003enet[j]);\n-\t\t}\n-\t}\n-\tif (ret != NETDEV_TX_OK)\n-\t\tnetif_stop_queue(dev);\n-\n-\treturn ret;\n-}\n-\n-/*\n- * shortcut for skb delivery\n- */\n-int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,\n-\t\tktime_t ktime)\n-{\n-\tstruct sk_buff *skb;\n-\tstruct can_frame *cf;\n-\n-\tskb = alloc_can_skb(netdev, \u0026cf);\n-\tif (!skb)\n-\t\treturn -ENOMEM;\n-\tmemcpy(cf, msg, sizeof(*msg));\n-\tskb-\u003etstamp = ktime;\n-\treturn netif_rx(skb);\n-}\n-\n-/*\n- * softing_handle_1\n- * pop 1 entry from the DPRAM queue, and process\n- */\n-static int softing_handle_1(struct softing *card)\n-{\n-\tstruct net_device *netdev;\n-\tstruct softing_priv *priv;\n-\tktime_t ktime;\n-\tstruct can_frame msg;\n-\tint cnt = 0, lost_msg;\n-\tuint8_t fifo_rd, fifo_wr, cmd;\n-\tuint8_t *ptr;\n-\tuint32_t tmp_u32;\n-\tuint8_t buf[DPRAM_RX_SIZE];\n-\n-\tmemset(\u0026msg, 0, sizeof(msg));\n-\t/* test for lost msgs */\n-\tlost_msg = ioread8(\u0026card-\u003edpram[DPRAM_RX_LOST]);\n-\tif (lost_msg) {\n-\t\tint j;\n-\t\t/* reset condition */\n-\t\tiowrite8(0, \u0026card-\u003edpram[DPRAM_RX_LOST]);\n-\t\t/* prepare msg */\n-\t\tmsg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;\n-\t\tmsg.len = CAN_ERR_DLC;\n-\t\tmsg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW;\n-\t\t/*\n-\t\t * service to all buses, we don't know which it was applicable\n-\t\t * but only service buses that are online\n-\t\t */\n-\t\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\t\tnetdev = card-\u003enet[j];\n-\t\t\tif (!netdev)\n-\t\t\t\tcontinue;\n-\t\t\tif (!canif_is_active(netdev))\n-\t\t\t\t/* a dead bus has no overflows */\n-\t\t\t\tcontinue;\n-\t\t\t++netdev-\u003estats.rx_over_errors;\n-\t\t\tsofting_netdev_rx(netdev, \u0026msg, 0);\n-\t\t}\n-\t\t/* prepare for other use */\n-\t\tmemset(\u0026msg, 0, sizeof(msg));\n-\t\t++cnt;\n-\t}\n-\n-\tfifo_rd = ioread8(\u0026card-\u003edpram[DPRAM_RX_RD]);\n-\tfifo_wr = ioread8(\u0026card-\u003edpram[DPRAM_RX_WR]);\n-\n-\tif (++fifo_rd \u003e= DPRAM_RX_CNT)\n-\t\tfifo_rd = 0;\n-\tif (fifo_wr == fifo_rd)\n-\t\treturn cnt;\n-\n-\tmemcpy_fromio(buf, \u0026card-\u003edpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd],\n-\t\t\tDPRAM_RX_SIZE);\n-\tmb();\n-\t/* trigger dual port RAM */\n-\tiowrite8(fifo_rd, \u0026card-\u003edpram[DPRAM_RX_RD]);\n-\n-\tptr = buf;\n-\tcmd = *ptr++;\n-\tif (cmd == 0xff)\n-\t\t/* not quite useful, probably the card has got out */\n-\t\treturn 0;\n-\tnetdev = card-\u003enet[0];\n-\tif (cmd \u0026 CMD_BUS2)\n-\t\tnetdev = card-\u003enet[1];\n-\tpriv = netdev_priv(netdev);\n-\n-\tif (cmd \u0026 CMD_ERR) {\n-\t\tuint8_t can_state, state;\n-\n-\t\tstate = *ptr++;\n-\n-\t\tmsg.can_id = CAN_ERR_FLAG;\n-\t\tmsg.len = CAN_ERR_DLC;\n-\n-\t\tif (state \u0026 SF_MASK_BUSOFF) {\n-\t\t\tcan_state = CAN_STATE_BUS_OFF;\n-\t\t\tmsg.can_id |= CAN_ERR_BUSOFF;\n-\t\t\tstate = STATE_BUSOFF;\n-\t\t} else if (state \u0026 SF_MASK_EPASSIVE) {\n-\t\t\tcan_state = CAN_STATE_ERROR_PASSIVE;\n-\t\t\tmsg.can_id |= CAN_ERR_CRTL;\n-\t\t\tmsg.data[1] = CAN_ERR_CRTL_TX_PASSIVE;\n-\t\t\tstate = STATE_EPASSIVE;\n-\t\t} else {\n-\t\t\tcan_state = CAN_STATE_ERROR_ACTIVE;\n-\t\t\tmsg.can_id |= CAN_ERR_CRTL;\n-\t\t\tstate = STATE_EACTIVE;\n-\t\t}\n-\t\t/* update DPRAM */\n-\t\tiowrite8(state, \u0026card-\u003edpram[priv-\u003eindex ?\n-\t\t\t\tDPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]);\n-\t\t/* timestamp */\n-\t\ttmp_u32 = le32_to_cpup((void *)ptr);\n-\t\tktime = softing_raw2ktime(card, tmp_u32);\n-\n-\t\t++netdev-\u003estats.rx_errors;\n-\t\t/* update internal status */\n-\t\tif (can_state != priv-\u003ecan.state) {\n-\t\t\tpriv-\u003ecan.state = can_state;\n-\t\t\tif (can_state == CAN_STATE_ERROR_PASSIVE)\n-\t\t\t\t++priv-\u003ecan.can_stats.error_passive;\n-\t\t\telse if (can_state == CAN_STATE_BUS_OFF) {\n-\t\t\t\t/* this calls can_close_cleanup() */\n-\t\t\t\t++priv-\u003ecan.can_stats.bus_off;\n-\t\t\t\tcan_bus_off(netdev);\n-\t\t\t\tnetif_stop_queue(netdev);\n-\t\t\t}\n-\t\t\t/* trigger socketcan */\n-\t\t\tsofting_netdev_rx(netdev, \u0026msg, ktime);\n-\t\t}\n-\n-\t} else {\n-\t\tif (cmd \u0026 CMD_RTR)\n-\t\t\tmsg.can_id |= CAN_RTR_FLAG;\n-\t\tmsg.len = can_cc_dlc2len(*ptr++);\n-\t\tif (cmd \u0026 CMD_XTD) {\n-\t\t\tmsg.can_id |= CAN_EFF_FLAG;\n-\t\t\tmsg.can_id |= le32_to_cpup((void *)ptr);\n-\t\t\tptr += 4;\n-\t\t} else {\n-\t\t\tmsg.can_id |= le16_to_cpup((void *)ptr);\n-\t\t\tptr += 2;\n-\t\t}\n-\t\t/* timestamp */\n-\t\ttmp_u32 = le32_to_cpup((void *)ptr);\n-\t\tptr += 4;\n-\t\tktime = softing_raw2ktime(card, tmp_u32);\n-\t\tif (!(msg.can_id \u0026 CAN_RTR_FLAG))\n-\t\t\tmemcpy(\u0026msg.data[0], ptr, 8);\n-\t\t/* update socket */\n-\t\tif (cmd \u0026 CMD_ACK) {\n-\t\t\t/* acknowledge, was tx msg */\n-\t\t\tstruct sk_buff *skb;\n-\t\t\tskb = priv-\u003ecan.echo_skb[priv-\u003etx.echo_get];\n-\t\t\tif (skb)\n-\t\t\t\tskb-\u003etstamp = ktime;\n-\t\t\t++netdev-\u003estats.tx_packets;\n-\t\t\tnetdev-\u003estats.tx_bytes +=\n-\t\t\t\tcan_get_echo_skb(netdev, priv-\u003etx.echo_get,\n-\t\t\t\t\t\t NULL);\n-\t\t\t++priv-\u003etx.echo_get;\n-\t\t\tif (priv-\u003etx.echo_get \u003e= TX_ECHO_SKB_MAX)\n-\t\t\t\tpriv-\u003etx.echo_get = 0;\n-\t\t\tif (priv-\u003etx.pending)\n-\t\t\t\t--priv-\u003etx.pending;\n-\t\t\tif (card-\u003etx.pending)\n-\t\t\t\t--card-\u003etx.pending;\n-\t\t} else {\n-\t\t\tint ret;\n-\n-\t\t\tret = softing_netdev_rx(netdev, \u0026msg, ktime);\n-\t\t\tif (ret == NET_RX_SUCCESS) {\n-\t\t\t\t++netdev-\u003estats.rx_packets;\n-\t\t\t\tif (!(msg.can_id \u0026 CAN_RTR_FLAG))\n-\t\t\t\t\tnetdev-\u003estats.rx_bytes += msg.len;\n-\t\t\t} else {\n-\t\t\t\t++netdev-\u003estats.rx_dropped;\n-\t\t\t}\n-\t\t}\n-\t}\n-\t++cnt;\n-\treturn cnt;\n-}\n-\n-/*\n- * real interrupt handler\n- */\n-static irqreturn_t softing_irq_thread(int irq, void *dev_id)\n-{\n-\tstruct softing *card = (struct softing *)dev_id;\n-\tstruct net_device *netdev;\n-\tstruct softing_priv *priv;\n-\tint j, offset, work_done;\n-\n-\twork_done = 0;\n-\tspin_lock_bh(\u0026card-\u003espin);\n-\twhile (softing_handle_1(card) \u003e 0) {\n-\t\t++card-\u003eirq.svc_count;\n-\t\t++work_done;\n-\t}\n-\tspin_unlock_bh(\u0026card-\u003espin);\n-\t/* resume tx queue's */\n-\toffset = card-\u003etx.last_bus;\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tif (card-\u003etx.pending \u003e= TXMAX)\n-\t\t\tbreak;\n-\t\tnetdev = card-\u003enet[(j + offset + 1) % card-\u003epdat-\u003enbus];\n-\t\tif (!netdev)\n-\t\t\tcontinue;\n-\t\tpriv = netdev_priv(netdev);\n-\t\tif (!canif_is_active(netdev))\n-\t\t\t/* it makes no sense to wake dead buses */\n-\t\t\tcontinue;\n-\t\tif (priv-\u003etx.pending \u003e= TX_ECHO_SKB_MAX)\n-\t\t\tcontinue;\n-\t\t++work_done;\n-\t\tnetif_wake_queue(netdev);\n-\t}\n-\treturn work_done ? IRQ_HANDLED : IRQ_NONE;\n-}\n-\n-/*\n- * interrupt routines:\n- * schedule the 'real interrupt handler'\n- */\n-static irqreturn_t softing_irq_v2(int irq, void *dev_id)\n-{\n-\tstruct softing *card = (struct softing *)dev_id;\n-\tuint8_t ir;\n-\n-\tir = ioread8(\u0026card-\u003edpram[DPRAM_V2_IRQ_TOHOST]);\n-\tiowrite8(0, \u0026card-\u003edpram[DPRAM_V2_IRQ_TOHOST]);\n-\treturn (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE;\n-}\n-\n-static irqreturn_t softing_irq_v1(int irq, void *dev_id)\n-{\n-\tstruct softing *card = (struct softing *)dev_id;\n-\tuint8_t ir;\n-\n-\tir = ioread8(\u0026card-\u003edpram[DPRAM_IRQ_TOHOST]);\n-\tiowrite8(0, \u0026card-\u003edpram[DPRAM_IRQ_TOHOST]);\n-\treturn ir ? IRQ_WAKE_THREAD : IRQ_NONE;\n-}\n-\n-/*\n- * netdev/candev interoperability\n- */\n-static int softing_netdev_open(struct net_device *ndev)\n-{\n-\tint ret;\n-\n-\t/* check or determine and set bittime */\n-\tret = open_candev(ndev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tret = softing_startstop(ndev, 1);\n-\tif (ret \u003c 0)\n-\t\tclose_candev(ndev);\n-\n-\treturn ret;\n-}\n-\n-static int softing_netdev_stop(struct net_device *ndev)\n-{\n-\tnetif_stop_queue(ndev);\n-\n-\t/* softing cycle does close_candev() */\n-\treturn softing_startstop(ndev, 0);\n-}\n-\n-static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode)\n-{\n-\tint ret;\n-\n-\tswitch (mode) {\n-\tcase CAN_MODE_START:\n-\t\t/* softing_startstop does close_candev() */\n-\t\tret = softing_startstop(ndev, 1);\n-\t\treturn ret;\n-\tcase CAN_MODE_STOP:\n-\tcase CAN_MODE_SLEEP:\n-\t\treturn -EOPNOTSUPP;\n-\t}\n-\treturn 0;\n-}\n-\n-/*\n- * Softing device management helpers\n- */\n-int softing_enable_irq(struct softing *card, int enable)\n-{\n-\tint ret;\n-\n-\tif (!card-\u003eirq.nr) {\n-\t\treturn 0;\n-\t} else if (card-\u003eirq.requested \u0026\u0026 !enable) {\n-\t\tfree_irq(card-\u003eirq.nr, card);\n-\t\tcard-\u003eirq.requested = 0;\n-\t} else if (!card-\u003eirq.requested \u0026\u0026 enable) {\n-\t\tret = request_threaded_irq(card-\u003eirq.nr,\n-\t\t\t\t(card-\u003epdat-\u003egeneration \u003e= 2) ?\n-\t\t\t\t\tsofting_irq_v2 : softing_irq_v1,\n-\t\t\t\tsofting_irq_thread, IRQF_SHARED,\n-\t\t\t\tdev_name(\u0026card-\u003epdev-\u003edev), card);\n-\t\tif (ret) {\n-\t\t\tdev_alert(\u0026card-\u003epdev-\u003edev,\n-\t\t\t\t\t\"request_threaded_irq(%u) failed\\n\",\n-\t\t\t\t\tcard-\u003eirq.nr);\n-\t\t\treturn ret;\n-\t\t}\n-\t\tcard-\u003eirq.requested = 1;\n-\t}\n-\treturn 0;\n-}\n-\n-static void softing_card_shutdown(struct softing *card)\n-{\n-\tint fw_up = 0;\n-\n-\tif (mutex_lock_interruptible(\u0026card-\u003efw.lock)) {\n-\t\t/* return -ERESTARTSYS */;\n-\t}\n-\tfw_up = card-\u003efw.up;\n-\tcard-\u003efw.up = 0;\n-\n-\tif (card-\u003eirq.requested \u0026\u0026 card-\u003eirq.nr) {\n-\t\tfree_irq(card-\u003eirq.nr, card);\n-\t\tcard-\u003eirq.requested = 0;\n-\t}\n-\tif (fw_up) {\n-\t\tif (card-\u003epdat-\u003eenable_irq)\n-\t\t\tcard-\u003epdat-\u003eenable_irq(card-\u003epdev, 0);\n-\t\tsofting_set_reset_dpram(card);\n-\t\tif (card-\u003epdat-\u003ereset)\n-\t\t\tcard-\u003epdat-\u003ereset(card-\u003epdev, 1);\n-\t}\n-\tmutex_unlock(\u0026card-\u003efw.lock);\n-}\n-\n-static int softing_card_boot(struct softing *card)\n-{\n-\tint ret, j;\n-\tstatic const uint8_t stream[] = {\n-\t\t0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, };\n-\tunsigned char back[sizeof(stream)];\n-\n-\tif (mutex_lock_interruptible(\u0026card-\u003efw.lock))\n-\t\treturn -ERESTARTSYS;\n-\tif (card-\u003efw.up) {\n-\t\tmutex_unlock(\u0026card-\u003efw.lock);\n-\t\treturn 0;\n-\t}\n-\t/* reset board */\n-\tif (card-\u003epdat-\u003eenable_irq)\n-\t\tcard-\u003epdat-\u003eenable_irq(card-\u003epdev, 1);\n-\t/* boot card */\n-\tsofting_set_reset_dpram(card);\n-\tif (card-\u003epdat-\u003ereset)\n-\t\tcard-\u003epdat-\u003ereset(card-\u003epdev, 1);\n-\tfor (j = 0; (j + sizeof(stream)) \u003c card-\u003edpram_size;\n-\t\t\tj += sizeof(stream)) {\n-\n-\t\tmemcpy_toio(\u0026card-\u003edpram[j], stream, sizeof(stream));\n-\t\t/* flush IO cache */\n-\t\tmb();\n-\t\tmemcpy_fromio(back, \u0026card-\u003edpram[j], sizeof(stream));\n-\n-\t\tif (!memcmp(back, stream, sizeof(stream)))\n-\t\t\tcontinue;\n-\t\t/* memory is not equal */\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"dpram failed at 0x%04x\\n\", j);\n-\t\tret = -EIO;\n-\t\tgoto failed;\n-\t}\n-\twmb();\n-\t/* load boot firmware */\n-\tret = softing_load_fw(card-\u003epdat-\u003eboot.fw, card, card-\u003edpram,\n-\t\t\t\tcard-\u003edpram_size,\n-\t\t\t\tcard-\u003epdat-\u003eboot.offs - card-\u003epdat-\u003eboot.addr);\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\t/* load loader firmware */\n-\tret = softing_load_fw(card-\u003epdat-\u003eload.fw, card, card-\u003edpram,\n-\t\t\t\tcard-\u003edpram_size,\n-\t\t\t\tcard-\u003epdat-\u003eload.offs - card-\u003epdat-\u003eload.addr);\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\n-\tif (card-\u003epdat-\u003ereset)\n-\t\tcard-\u003epdat-\u003ereset(card-\u003epdev, 0);\n-\tsofting_clr_reset_dpram(card);\n-\tret = softing_bootloader_command(card, 0, \"card boot\");\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\tret = softing_load_app_fw(card-\u003epdat-\u003eapp.fw, card);\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\n-\tret = softing_chip_poweron(card);\n-\tif (ret \u003c 0)\n-\t\tgoto failed;\n-\n-\tcard-\u003efw.up = 1;\n-\tmutex_unlock(\u0026card-\u003efw.lock);\n-\treturn 0;\n-failed:\n-\tcard-\u003efw.up = 0;\n-\tif (card-\u003epdat-\u003eenable_irq)\n-\t\tcard-\u003epdat-\u003eenable_irq(card-\u003epdev, 0);\n-\tsofting_set_reset_dpram(card);\n-\tif (card-\u003epdat-\u003ereset)\n-\t\tcard-\u003epdat-\u003ereset(card-\u003epdev, 1);\n-\tmutex_unlock(\u0026card-\u003efw.lock);\n-\treturn ret;\n-}\n-\n-/*\n- * netdev sysfs\n- */\n-static ssize_t show_chip(struct device *dev, struct device_attribute *attr,\n-\t\tchar *buf)\n-{\n-\tstruct net_device *ndev = to_net_dev(dev);\n-\tstruct softing_priv *priv = netdev2softing(ndev);\n-\n-\treturn sprintf(buf, \"%i\\n\", priv-\u003echip);\n-}\n-\n-static ssize_t show_output(struct device *dev, struct device_attribute *attr,\n-\t\tchar *buf)\n-{\n-\tstruct net_device *ndev = to_net_dev(dev);\n-\tstruct softing_priv *priv = netdev2softing(ndev);\n-\n-\treturn sprintf(buf, \"0x%02x\\n\", priv-\u003eoutput);\n-}\n-\n-static ssize_t store_output(struct device *dev, struct device_attribute *attr,\n-\t\tconst char *buf, size_t count)\n-{\n-\tstruct net_device *ndev = to_net_dev(dev);\n-\tstruct softing_priv *priv = netdev2softing(ndev);\n-\tstruct softing *card = priv-\u003ecard;\n-\tunsigned long val;\n-\tint ret;\n-\n-\tret = kstrtoul(buf, 0, \u0026val);\n-\tif (ret \u003c 0)\n-\t\treturn ret;\n-\tval \u0026= 0xFF;\n-\n-\tret = mutex_lock_interruptible(\u0026card-\u003efw.lock);\n-\tif (ret)\n-\t\treturn -ERESTARTSYS;\n-\tif (netif_running(ndev)) {\n-\t\tmutex_unlock(\u0026card-\u003efw.lock);\n-\t\treturn -EBUSY;\n-\t}\n-\tpriv-\u003eoutput = val;\n-\tmutex_unlock(\u0026card-\u003efw.lock);\n-\treturn count;\n-}\n-\n-static const DEVICE_ATTR(chip, 0444, show_chip, NULL);\n-static const DEVICE_ATTR(output, 0644, show_output, store_output);\n-\n-static const struct attribute *const netdev_sysfs_attrs[] = {\n-\t\u0026dev_attr_chip.attr,\n-\t\u0026dev_attr_output.attr,\n-\tNULL,\n-};\n-static const struct attribute_group netdev_sysfs_group = {\n-\t.name = NULL,\n-\t.attrs = (struct attribute **)netdev_sysfs_attrs,\n-};\n-\n-static const struct net_device_ops softing_netdev_ops = {\n-\t.ndo_open = softing_netdev_open,\n-\t.ndo_stop = softing_netdev_stop,\n-\t.ndo_start_xmit\t= softing_netdev_start_xmit,\n-};\n-\n-static const struct ethtool_ops softing_ethtool_ops = {\n-\t.get_ts_info = ethtool_op_get_ts_info,\n-};\n-\n-static const struct can_bittiming_const softing_btr_const = {\n-\t.name = KBUILD_MODNAME,\n-\t.tseg1_min = 1,\n-\t.tseg1_max = 16,\n-\t.tseg2_min = 1,\n-\t.tseg2_max = 8,\n-\t.sjw_max = 4, /* overruled */\n-\t.brp_min = 1,\n-\t.brp_max = 32, /* overruled */\n-\t.brp_inc = 1,\n-};\n-\n-\n-static struct net_device *softing_netdev_create(struct softing *card,\n-\t\t\t\t\t\tuint16_t chip_id)\n-{\n-\tstruct net_device *netdev;\n-\tstruct softing_priv *priv;\n-\n-\tnetdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);\n-\tif (!netdev) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"alloc_candev failed\\n\");\n-\t\treturn NULL;\n-\t}\n-\tpriv = netdev_priv(netdev);\n-\tpriv-\u003enetdev = netdev;\n-\tpriv-\u003ecard = card;\n-\tmemcpy(\u0026priv-\u003ebtr_const, \u0026softing_btr_const, sizeof(priv-\u003ebtr_const));\n-\tpriv-\u003ebtr_const.brp_max = card-\u003epdat-\u003emax_brp;\n-\tpriv-\u003ebtr_const.sjw_max = card-\u003epdat-\u003emax_sjw;\n-\tpriv-\u003ecan.bittiming_const = \u0026priv-\u003ebtr_const;\n-\tpriv-\u003ecan.clock.freq = 8000000;\n-\tpriv-\u003echip = chip_id;\n-\tpriv-\u003eoutput = softing_default_output(netdev);\n-\tSET_NETDEV_DEV(netdev, \u0026card-\u003epdev-\u003edev);\n-\n-\tnetdev-\u003eflags |= IFF_ECHO;\n-\tnetdev-\u003enetdev_ops = \u0026softing_netdev_ops;\n-\tnetdev-\u003eethtool_ops = \u0026softing_ethtool_ops;\n-\tpriv-\u003ecan.do_set_mode = softing_candev_set_mode;\n-\tpriv-\u003ecan.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;\n-\n-\treturn netdev;\n-}\n-\n-static int softing_netdev_register(struct net_device *netdev)\n-{\n-\tint ret;\n-\n-\tret = register_candev(netdev);\n-\tif (ret) {\n-\t\tdev_alert(\u0026netdev-\u003edev, \"register failed\\n\");\n-\t\treturn ret;\n-\t}\n-\tif (sysfs_create_group(\u0026netdev-\u003edev.kobj, \u0026netdev_sysfs_group) \u003c 0)\n-\t\tnetdev_alert(netdev, \"sysfs group failed\\n\");\n-\n-\treturn 0;\n-}\n-\n-static void softing_netdev_cleanup(struct net_device *netdev)\n-{\n-\tsysfs_remove_group(\u0026netdev-\u003edev.kobj, \u0026netdev_sysfs_group);\n-\tunregister_candev(netdev);\n-\tfree_candev(netdev);\n-}\n-\n-/*\n- * sysfs for Platform device\n- */\n-#define DEV_ATTR_RO(name, member) \\\n-static ssize_t show_##name(struct device *dev, \\\n-\t\tstruct device_attribute *attr, char *buf) \\\n-{ \\\n-\tstruct softing *card = dev_get_drvdata(dev); \\\n-\treturn sprintf(buf, \"%u\\n\", card-\u003emember); \\\n-} \\\n-static DEVICE_ATTR(name, 0444, show_##name, NULL)\n-\n-#define DEV_ATTR_RO_STR(name, member) \\\n-static ssize_t show_##name(struct device *dev, \\\n-\t\tstruct device_attribute *attr, char *buf) \\\n-{ \\\n-\tstruct softing *card = dev_get_drvdata(dev); \\\n-\treturn sprintf(buf, \"%s\\n\", card-\u003emember); \\\n-} \\\n-static DEVICE_ATTR(name, 0444, show_##name, NULL)\n-\n-DEV_ATTR_RO(serial, id.serial);\n-DEV_ATTR_RO_STR(firmware, pdat-\u003eapp.fw);\n-DEV_ATTR_RO(firmware_version, id.fw_version);\n-DEV_ATTR_RO_STR(hardware, pdat-\u003ename);\n-DEV_ATTR_RO(hardware_version, id.hw_version);\n-DEV_ATTR_RO(license, id.license);\n-\n-static struct attribute *softing_pdev_attrs[] = {\n-\t\u0026dev_attr_serial.attr,\n-\t\u0026dev_attr_firmware.attr,\n-\t\u0026dev_attr_firmware_version.attr,\n-\t\u0026dev_attr_hardware.attr,\n-\t\u0026dev_attr_hardware_version.attr,\n-\t\u0026dev_attr_license.attr,\n-\tNULL,\n-};\n-\n-static const struct attribute_group softing_pdev_group = {\n-\t.name = NULL,\n-\t.attrs = softing_pdev_attrs,\n-};\n-\n-/*\n- * platform driver\n- */\n-static void softing_pdev_remove(struct platform_device *pdev)\n-{\n-\tstruct softing *card = platform_get_drvdata(pdev);\n-\tint j;\n-\n-\t/* first, disable card*/\n-\tsofting_card_shutdown(card);\n-\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tif (!card-\u003enet[j])\n-\t\t\tcontinue;\n-\t\tsofting_netdev_cleanup(card-\u003enet[j]);\n-\t\tcard-\u003enet[j] = NULL;\n-\t}\n-\tsysfs_remove_group(\u0026pdev-\u003edev.kobj, \u0026softing_pdev_group);\n-\n-\tiounmap(card-\u003edpram);\n-\tkfree(card);\n-}\n-\n-static int softing_pdev_probe(struct platform_device *pdev)\n-{\n-\tconst struct softing_platform_data *pdat = dev_get_platdata(\u0026pdev-\u003edev);\n-\tstruct softing *card;\n-\tstruct net_device *netdev;\n-\tstruct softing_priv *priv;\n-\tstruct resource *pres;\n-\tint ret;\n-\tint j;\n-\n-\tif (!pdat) {\n-\t\tdev_warn(\u0026pdev-\u003edev, \"no platform data\\n\");\n-\t\treturn -EINVAL;\n-\t}\n-\tif (pdat-\u003enbus \u003e ARRAY_SIZE(card-\u003enet)) {\n-\t\tdev_warn(\u0026pdev-\u003edev, \"%u nets??\\n\", pdat-\u003enbus);\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tcard = kzalloc_obj(*card);\n-\tif (!card)\n-\t\treturn -ENOMEM;\n-\tcard-\u003epdat = pdat;\n-\tcard-\u003epdev = pdev;\n-\tplatform_set_drvdata(pdev, card);\n-\tmutex_init(\u0026card-\u003efw.lock);\n-\tspin_lock_init(\u0026card-\u003espin);\n-\n-\tret = -EINVAL;\n-\tpres = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n-\tif (!pres)\n-\t\tgoto platform_resource_failed;\n-\tcard-\u003edpram_phys = pres-\u003estart;\n-\tcard-\u003edpram_size = resource_size(pres);\n-\tcard-\u003edpram = ioremap(card-\u003edpram_phys, card-\u003edpram_size);\n-\tif (!card-\u003edpram) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"dpram ioremap failed\\n\");\n-\t\tgoto ioremap_failed;\n-\t}\n-\n-\tpres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);\n-\tif (pres)\n-\t\tcard-\u003eirq.nr = pres-\u003estart;\n-\n-\t/* reset card */\n-\tret = softing_card_boot(card);\n-\tif (ret \u003c 0) {\n-\t\tdev_alert(\u0026pdev-\u003edev, \"failed to boot\\n\");\n-\t\tgoto boot_failed;\n-\t}\n-\n-\t/* only now, the chip's are known */\n-\tcard-\u003eid.freq = card-\u003epdat-\u003efreq;\n-\n-\tret = sysfs_create_group(\u0026pdev-\u003edev.kobj, \u0026softing_pdev_group);\n-\tif (ret \u003c 0) {\n-\t\tdev_alert(\u0026card-\u003epdev-\u003edev, \"sysfs failed\\n\");\n-\t\tgoto sysfs_failed;\n-\t}\n-\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tcard-\u003enet[j] = netdev =\n-\t\t\tsofting_netdev_create(card, card-\u003eid.chip[j]);\n-\t\tif (!netdev) {\n-\t\t\tdev_alert(\u0026pdev-\u003edev, \"failed to make can[%i]\", j);\n-\t\t\tret = -ENOMEM;\n-\t\t\tgoto netdev_failed;\n-\t\t}\n-\t\tnetdev-\u003edev_id = j;\n-\t\tpriv = netdev_priv(card-\u003enet[j]);\n-\t\tpriv-\u003eindex = j;\n-\t\tret = softing_netdev_register(netdev);\n-\t\tif (ret) {\n-\t\t\tfree_candev(netdev);\n-\t\t\tcard-\u003enet[j] = NULL;\n-\t\t\tdev_alert(\u0026card-\u003epdev-\u003edev,\n-\t\t\t\t\t\"failed to register can[%i]\\n\", j);\n-\t\t\tgoto netdev_failed;\n-\t\t}\n-\t}\n-\tdev_info(\u0026card-\u003epdev-\u003edev, \"%s ready.\\n\", card-\u003epdat-\u003ename);\n-\treturn 0;\n-\n-netdev_failed:\n-\tfor (j = 0; j \u003c ARRAY_SIZE(card-\u003enet); ++j) {\n-\t\tif (!card-\u003enet[j])\n-\t\t\tcontinue;\n-\t\tsofting_netdev_cleanup(card-\u003enet[j]);\n-\t}\n-\tsysfs_remove_group(\u0026pdev-\u003edev.kobj, \u0026softing_pdev_group);\n-sysfs_failed:\n-\tsofting_card_shutdown(card);\n-boot_failed:\n-\tiounmap(card-\u003edpram);\n-ioremap_failed:\n-platform_resource_failed:\n-\tkfree(card);\n-\treturn ret;\n-}\n-\n-static struct platform_driver softing_driver = {\n-\t.driver = {\n-\t\t.name = KBUILD_MODNAME,\n-\t},\n-\t.probe = softing_pdev_probe,\n-\t.remove = softing_pdev_remove,\n-};\n-\n-module_platform_driver(softing_driver);\n-\n-MODULE_ALIAS(\"platform:softing\");\n-MODULE_DESCRIPTION(\"Softing DPRAM CAN driver\");\n-MODULE_AUTHOR(\"Kurt Van Dijck \u003ckurt.van.dijck@eia.be\u003e\");\n-MODULE_LICENSE(\"GPL v2\");\ndiff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h\ndeleted file mode 100644\nindex cd8d7904c5f08..0000000000000\n--- a/drivers/net/can/softing/softing_platform.h\n+++ /dev/null\n@@ -1,41 +0,0 @@\n-/* SPDX-License-Identifier: GPL-2.0 */\n-\n-#include \u003clinux/platform_device.h\u003e\n-\n-#ifndef _SOFTING_DEVICE_H_\n-#define _SOFTING_DEVICE_H_\n-\n-/* softing firmware directory prefix */\n-#define fw_dir \"softing-4.6/\"\n-\n-struct softing_platform_data {\n-\tunsigned int manf;\n-\tunsigned int prod;\n-\t/*\n-\t * generation\n-\t * 1st with NEC or SJA1000\n-\t * 8bit, exclusive interrupt, ...\n-\t * 2nd only SJA1000\n-\t * 16bit, shared interrupt\n-\t */\n-\tint generation;\n-\tint nbus; /* # buses on device */\n-\tunsigned int freq; /* operating frequency in Hz */\n-\tunsigned int max_brp;\n-\tunsigned int max_sjw;\n-\tunsigned long dpram_size;\n-\tconst char *name;\n-\tstruct {\n-\t\tunsigned long offs;\n-\t\tunsigned long addr;\n-\t\tconst char *fw;\n-\t} boot, load, app;\n-\t/*\n-\t * reset() function\n-\t * bring pdev in or out of reset, depending on value\n-\t */\n-\tint (*reset)(struct platform_device *pdev, int value);\n-\tint (*enable_irq)(struct platform_device *pdev, int value);\n-};\n-\n-#endif\ndiff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c\nindex ae90e6716de5b..076a3efa1bfff 100644\n--- a/drivers/net/can/spi/hi311x.c\n+++ b/drivers/net/can/spi/hi311x.c\n@@ -972,7 +972,7 @@ static void hi3110_can_remove(struct spi_device *spi)\n \tfree_candev(net);\n }\n \n-static int __maybe_unused hi3110_can_suspend(struct device *dev)\n+static int hi3110_can_suspend(struct device *dev)\n {\n \tstruct spi_device *spi = to_spi_device(dev);\n \tstruct hi3110_priv *priv = spi_get_drvdata(spi);\n@@ -1002,7 +1002,7 @@ static int __maybe_unused hi3110_can_suspend(struct device *dev)\n \treturn 0;\n }\n \n-static int __maybe_unused hi3110_can_resume(struct device *dev)\n+static int hi3110_can_resume(struct device *dev)\n {\n \tstruct spi_device *spi = to_spi_device(dev);\n \tstruct hi3110_priv *priv = spi_get_drvdata(spi);\n@@ -1022,13 +1022,13 @@ static int __maybe_unused hi3110_can_resume(struct device *dev)\n \treturn 0;\n }\n \n-static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend, hi3110_can_resume);\n+static DEFINE_SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend, hi3110_can_resume);\n \n static struct spi_driver hi3110_can_driver = {\n \t.driver = {\n \t\t.name = DEVICE_NAME,\n \t\t.of_match_table = hi3110_of_match,\n-\t\t.pm = \u0026hi3110_can_pm_ops,\n+\t\t.pm = pm_sleep_ptr(\u0026hi3110_can_pm_ops),\n \t},\n \t.id_table = hi3110_id_table,\n \t.probe = hi3110_can_probe,\ndiff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c\nindex 0d0190ae094a1..d971890487b6c 100644\n--- a/drivers/net/can/spi/mcp251x.c\n+++ b/drivers/net/can/spi/mcp251x.c\n@@ -1490,7 +1490,7 @@ static void mcp251x_can_remove(struct spi_device *spi)\n \tfree_candev(net);\n }\n \n-static int __maybe_unused mcp251x_can_suspend(struct device *dev)\n+static int mcp251x_can_suspend(struct device *dev)\n {\n \tstruct spi_device *spi = to_spi_device(dev);\n \tstruct mcp251x_priv *priv = spi_get_drvdata(spi);\n@@ -1517,7 +1517,7 @@ static int __maybe_unused mcp251x_can_suspend(struct device *dev)\n \treturn 0;\n }\n \n-static int __maybe_unused mcp251x_can_resume(struct device *dev)\n+static int mcp251x_can_resume(struct device *dev)\n {\n \tstruct spi_device *spi = to_spi_device(dev);\n \tstruct mcp251x_priv *priv = spi_get_drvdata(spi);\n@@ -1551,14 +1551,14 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev)\n \treturn 0;\n }\n \n-static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,\n+static DEFINE_SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,\n \tmcp251x_can_resume);\n \n static struct spi_driver mcp251x_can_driver = {\n \t.driver = {\n \t\t.name = DEVICE_NAME,\n \t\t.of_match_table = mcp251x_of_match,\n-\t\t.pm = \u0026mcp251x_can_pm_ops,\n+\t\t.pm = pm_sleep_ptr(\u0026mcp251x_can_pm_ops),\n \t},\n \t.id_table = mcp251x_id_table,\n \t.probe = mcp251x_can_probe,\ndiff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c\nindex f441f2265299e..8759bc05bd8f0 100644\n--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c\n+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c\n@@ -2213,6 +2213,7 @@ MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table);\n \n static int mcp251xfd_probe(struct spi_device *spi)\n {\n+\tconst struct mcp251xfd_devtype_data *devtype_data;\n \tstruct net_device *ndev;\n \tstruct mcp251xfd_priv *priv;\n \tstruct gpio_desc *rx_int;\n@@ -2222,6 +2223,10 @@ static int mcp251xfd_probe(struct spi_device *spi)\n \tu32 freq = 0;\n \tint err;\n \n+\tdevtype_data = spi_get_device_match_data(spi);\n+\tif (!devtype_data)\n+\t\treturn -ENODATA;\n+\n \tif (!spi-\u003eirq)\n \t\treturn dev_err_probe(\u0026spi-\u003edev, -ENXIO,\n \t\t\t\t     \"No IRQ specified (maybe node \\\"interrupts-extended\\\" in DT missing)!\\n\");\n@@ -2307,7 +2312,7 @@ static int mcp251xfd_probe(struct spi_device *spi)\n \tpriv-\u003ereg_vdd = reg_vdd;\n \tpriv-\u003ereg_xceiver = reg_xceiver;\n \tpriv-\u003exstbyen = device_property_present(\u0026spi-\u003edev, \"microchip,xstbyen\");\n-\tpriv-\u003edevtype_data = *(struct mcp251xfd_devtype_data *)spi_get_device_match_data(spi);\n+\tpriv-\u003edevtype_data = *devtype_data;\n \n \t/* Errata Reference:\n \t * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789E 4.,\ndiff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c\nindex af52285d5a4e0..76db6d09d1e6b 100644\n--- a/drivers/net/can/sun4i_can.c\n+++ b/drivers/net/can/sun4i_can.c\n@@ -812,9 +812,12 @@ MODULE_DEVICE_TABLE(of, sun4ican_of_match);\n static void sun4ican_remove(struct platform_device *pdev)\n {\n \tstruct net_device *dev = platform_get_drvdata(pdev);\n+\tstruct sun4ican_priv *priv = netdev_priv(dev);\n+\tstruct clk *clk = priv-\u003eclk;\n \n \tunregister_netdev(dev);\n \tfree_candev(dev);\n+\tclk_put(clk);\n }\n \n static int sun4ican_probe(struct platform_device *pdev)\n@@ -854,13 +857,13 @@ static int sun4ican_probe(struct platform_device *pdev)\n \tirq = platform_get_irq(pdev, 0);\n \tif (irq \u003c 0) {\n \t\terr = -ENODEV;\n-\t\tgoto exit;\n+\t\tgoto exit_put_clk;\n \t}\n \n \taddr = devm_platform_ioremap_resource(pdev, 0);\n \tif (IS_ERR(addr)) {\n \t\terr = PTR_ERR(addr);\n-\t\tgoto exit;\n+\t\tgoto exit_put_clk;\n \t}\n \n \tdev = alloc_candev(sizeof(struct sun4ican_priv), 1);\n@@ -868,7 +871,7 @@ static int sun4ican_probe(struct platform_device *pdev)\n \t\tdev_err(\u0026pdev-\u003edev,\n \t\t\t\"could not allocate memory for CAN device\\n\");\n \t\terr = -ENOMEM;\n-\t\tgoto exit;\n+\t\tgoto exit_put_clk;\n \t}\n \n \tdev-\u003enetdev_ops = \u0026sun4ican_netdev_ops;\n@@ -908,6 +911,8 @@ static int sun4ican_probe(struct platform_device *pdev)\n \n exit_free:\n \tfree_candev(dev);\n+exit_put_clk:\n+\tclk_put(clk);\n exit:\n \treturn err;\n }\ndiff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c\nindex 24cf8f651f8f1..2d31f0b86859c 100644\n--- a/drivers/net/can/usb/ems_usb.c\n+++ b/drivers/net/can/usb/ems_usb.c\n@@ -748,7 +748,7 @@ static void unlink_all_urbs(struct ems_usb *dev)\n {\n \tint i;\n \n-\tusb_unlink_urb(dev-\u003eintr_urb);\n+\tusb_kill_urb(dev-\u003eintr_urb);\n \n \tusb_kill_anchored_urbs(\u0026dev-\u003erx_submitted);\n \ndiff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h\nindex 46a1b6907a500..2e862120ec3ff 100644\n--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h\n+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h\n@@ -161,7 +161,6 @@ struct kvaser_usb_net_priv {\n  * @dev_get_data_busparams:\treadback data busparams\n  * @dev_get_berr_counter:\tused for can.do_get_berr_counter\n  *\n- * @dev_setup_endpoints:\tsetup USB in and out endpoints\n  * @dev_init_card:\t\tinitialize card\n  * @dev_init_channel:\t\tinitialize channel\n  * @dev_remove_channel:\t\tuninitialize channel\n@@ -189,7 +188,6 @@ struct kvaser_usb_dev_ops {\n \tint (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv);\n \tint (*dev_get_berr_counter)(const struct net_device *netdev,\n \t\t\t\t    struct can_berr_counter *bec);\n-\tint (*dev_setup_endpoints)(struct kvaser_usb *dev);\n \tint (*dev_init_card)(struct kvaser_usb *dev);\n \tint (*dev_init_channel)(struct kvaser_usb_net_priv *priv);\n \tvoid (*dev_remove_channel)(struct kvaser_usb_net_priv *priv);\ndiff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c\nindex d0a2a2a33c1c8..9687dfb89b4cc 100644\n--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c\n+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c\n@@ -926,6 +926,23 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)\n \treturn err;\n }\n \n+static int kvaser_usb_setup_endpoints(struct kvaser_usb *dev)\n+{\n+\tstruct usb_host_interface *iface_desc;\n+\tint ret;\n+\n+\tiface_desc = dev-\u003eintf-\u003ecur_altsetting;\n+\n+\t/* use first bulk endpoint for in and out */\n+\tret = usb_find_common_endpoints(iface_desc, \u0026dev-\u003ebulk_in,\n+\t\t\t\t\t\u0026dev-\u003ebulk_out, NULL, NULL);\n+\n+\tif (ret)\n+\t\treturn -ENODEV;\n+\n+\treturn 0;\n+}\n+\n static int kvaser_usb_probe(struct usb_interface *intf,\n \t\t\t    const struct usb_device_id *id)\n {\n@@ -949,7 +966,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,\n \tdev-\u003edriver_info = driver_info;\n \tops = driver_info-\u003eops;\n \n-\terr = ops-\u003edev_setup_endpoints(dev);\n+\terr = kvaser_usb_setup_endpoints(dev);\n \tif (err) {\n \t\tdev_err_probe(\u0026intf-\u003edev, err, \"Cannot get usb endpoint(s)\");\n \t\tgoto free_devlink;\ndiff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c\nindex efbb7bed34c9d..2220d197abb55 100644\n--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c\n+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c\n@@ -37,9 +37,6 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_kcan;\n static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc;\n static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt;\n \n-#define KVASER_USB_HYDRA_BULK_EP_IN_ADDR\t0x82\n-#define KVASER_USB_HYDRA_BULK_EP_OUT_ADDR\t0x02\n-\n #define KVASER_USB_HYDRA_MAX_TRANSID\t\t0xff\n #define KVASER_USB_HYDRA_MIN_TRANSID\t\t0x01\n \n@@ -536,6 +533,82 @@ static size_t kvaser_usb_hydra_cmd_size(struct kvaser_cmd *cmd)\n \treturn ret;\n }\n \n+/* -EAGAIN means incomplete; -EINVAL rejects an invalid command length. */\n+static int kvaser_usb_hydra_cmd_size_rx(struct kvaser_cmd *cmd,\n+\t\t\t\t\tsize_t remaining, size_t *cmd_len)\n+{\n+\tif (remaining \u003c sizeof(cmd-\u003eheader.cmd_no))\n+\t\treturn -EAGAIN;\n+\n+\tif (cmd-\u003eheader.cmd_no == CMD_EXTENDED \u0026\u0026\n+\t    remaining \u003c offsetof(struct kvaser_cmd_ext, cmd_no_ext))\n+\t\treturn -EAGAIN;\n+\n+\t*cmd_len = kvaser_usb_hydra_cmd_size(cmd);\n+\tif (cmd-\u003eheader.cmd_no != CMD_EXTENDED)\n+\t\treturn 0;\n+\n+\tif (*cmd_len \u003c offsetof(struct kvaser_cmd_ext, rx_can) ||\n+\t    *cmd_len \u003e KVASER_USB_HYDRA_MAX_CMD_LEN)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static int kvaser_usb_hydra_verify_cmd_size(const struct kvaser_cmd *cmd,\n+\t\t\t\t\t    size_t cmd_len)\n+{\n+\tconst struct kvaser_cmd_ext *cmd_ext;\n+\tsize_t min_len;\n+\n+\tif (cmd-\u003eheader.cmd_no != CMD_EXTENDED)\n+\t\treturn 0;\n+\n+\tcmd_ext = (const struct kvaser_cmd_ext *)cmd;\n+\n+\t/* Keep this switch in sync with kvaser_usb_hydra_handle_cmd_ext(). */\n+\tswitch (cmd_ext-\u003ecmd_no_ext) {\n+\tcase CMD_TX_ACKNOWLEDGE_FD:\n+\t\tmin_len = offsetof(struct kvaser_cmd_ext, tx_ack.timestamp) +\n+\t\t\t  sizeof(cmd_ext-\u003etx_ack.timestamp);\n+\t\tbreak;\n+\n+\tcase CMD_RX_MESSAGE_FD: {\n+\t\tu32 flags;\n+\n+\t\tmin_len = offsetof(struct kvaser_cmd_ext, rx_can.kcan_payload);\n+\t\tif (cmd_len \u003c min_len)\n+\t\t\treturn -EINVAL;\n+\n+\t\tflags = le32_to_cpu(cmd_ext-\u003erx_can.flags);\n+\t\tif (flags \u0026 KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {\n+\t\t\tmin_len += sizeof(cmd_ext-\u003erx_can.err_frame_data);\n+\t\t} else if (!(flags \u0026 KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME)) {\n+\t\t\tu32 kcan_header;\n+\t\t\tu8 dlc;\n+\n+\t\t\tkcan_header = le32_to_cpu(cmd_ext-\u003erx_can.kcan_header);\n+\t\t\tdlc = (kcan_header \u0026 KVASER_USB_KCAN_DATA_DLC_MASK) \u003e\u003e\n+\t\t\t\tKVASER_USB_KCAN_DATA_DLC_SHIFT;\n+\n+\t\t\tif (flags \u0026 KVASER_USB_HYDRA_CF_FLAG_FDF)\n+\t\t\t\tmin_len += can_fd_dlc2len(dlc);\n+\t\t\telse\n+\t\t\t\tmin_len += can_cc_dlc2len(dlc);\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+\n+\tif (cmd_len \u003c min_len)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n static struct kvaser_usb_net_priv *\n kvaser_usb_hydra_net_priv_from_cmd(const struct kvaser_usb *dev,\n \t\t\t\t   const struct kvaser_cmd *cmd)\n@@ -675,8 +748,9 @@ static int kvaser_usb_hydra_wait_cmd(const struct kvaser_usb *dev, u8 cmd_no,\n \t\t\tsize_t cmd_len;\n \n \t\t\ttmp_cmd = buf + pos;\n-\t\t\tcmd_len = kvaser_usb_hydra_cmd_size(tmp_cmd);\n-\t\t\tif (pos + cmd_len \u003e actual_len) {\n+\t\t\terr = kvaser_usb_hydra_cmd_size_rx(tmp_cmd, actual_len - pos, \u0026cmd_len);\n+\t\t\tif (err || pos + cmd_len \u003e actual_len ||\n+\t\t\t    kvaser_usb_hydra_verify_cmd_size(tmp_cmd, cmd_len)) {\n \t\t\t\tdev_err_ratelimited(\u0026dev-\u003eintf-\u003edev,\n \t\t\t\t\t\t    \"Format error\\n\");\n \t\t\t\tbreak;\n@@ -1733,32 +1807,6 @@ static int kvaser_usb_hydra_get_berr_counter(const struct net_device *netdev,\n \treturn 0;\n }\n \n-static int kvaser_usb_hydra_setup_endpoints(struct kvaser_usb *dev)\n-{\n-\tconst struct usb_host_interface *iface_desc;\n-\tstruct usb_endpoint_descriptor *ep;\n-\tint i;\n-\n-\tiface_desc = dev-\u003eintf-\u003ecur_altsetting;\n-\n-\tfor (i = 0; i \u003c iface_desc-\u003edesc.bNumEndpoints; ++i) {\n-\t\tep = \u0026iface_desc-\u003eendpoint[i].desc;\n-\n-\t\tif (!dev-\u003ebulk_in \u0026\u0026 usb_endpoint_is_bulk_in(ep) \u0026\u0026\n-\t\t    ep-\u003ebEndpointAddress == KVASER_USB_HYDRA_BULK_EP_IN_ADDR)\n-\t\t\tdev-\u003ebulk_in = ep;\n-\n-\t\tif (!dev-\u003ebulk_out \u0026\u0026 usb_endpoint_is_bulk_out(ep) \u0026\u0026\n-\t\t    ep-\u003ebEndpointAddress == KVASER_USB_HYDRA_BULK_EP_OUT_ADDR)\n-\t\t\tdev-\u003ebulk_out = ep;\n-\n-\t\tif (dev-\u003ebulk_in \u0026\u0026 dev-\u003ebulk_out)\n-\t\t\treturn 0;\n-\t}\n-\n-\treturn -ENODEV;\n-}\n-\n static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev)\n {\n \tint err;\n@@ -2120,27 +2168,61 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,\n \tspin_lock_irqsave(usb_rx_leftover_lock, irq_flags);\n \tusb_rx_leftover_len = card_data-\u003eusb_rx_leftover_len;\n \tif (usb_rx_leftover_len) {\n+\t\tconst size_t cmd_size_field_end = offsetof(struct kvaser_cmd_ext, cmd_no_ext);\n \t\tint remaining_bytes;\n+\t\tint err;\n \n \t\tcmd = (struct kvaser_cmd *)card_data-\u003eusb_rx_leftover;\n \n-\t\tcmd_len = kvaser_usb_hydra_cmd_size(cmd);\n+\t\tif (cmd-\u003eheader.cmd_no == CMD_EXTENDED \u0026\u0026\n+\t\t    usb_rx_leftover_len \u003c cmd_size_field_end) {\n+\t\t\tremaining_bytes = min_t(int, len, cmd_size_field_end - usb_rx_leftover_len);\n+\n+\t\t\tmemcpy(card_data-\u003eusb_rx_leftover + usb_rx_leftover_len, buf,\n+\t\t\t       remaining_bytes);\n+\t\t\tusb_rx_leftover_len += remaining_bytes;\n+\t\t\tcard_data-\u003eusb_rx_leftover_len = usb_rx_leftover_len;\n+\t\t\tpos += remaining_bytes;\n+\n+\t\t\tif (usb_rx_leftover_len \u003c cmd_size_field_end) {\n+\t\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock,\n+\t\t\t\t\t\t       irq_flags);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n \n-\t\tremaining_bytes = min_t(unsigned int, len,\n+\t\terr = kvaser_usb_hydra_cmd_size_rx(cmd, usb_rx_leftover_len,\n+\t\t\t\t\t\t   \u0026cmd_len);\n+\t\tif (err || cmd_len \u003c usb_rx_leftover_len) {\n+\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\n+\t\t\tcard_data-\u003eusb_rx_leftover_len = 0;\n+\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tremaining_bytes = min_t(unsigned int, len - pos,\n \t\t\t\t\tcmd_len - usb_rx_leftover_len);\n \t\t/* Make sure we do not overflow usb_rx_leftover */\n \t\tif (remaining_bytes + usb_rx_leftover_len \u003e\n \t\t\t\t\t\tKVASER_USB_HYDRA_MAX_CMD_LEN) {\n \t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\n+\t\t\tcard_data-\u003eusb_rx_leftover_len = 0;\n \t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\n \t\t\treturn;\n \t\t}\n \n-\t\tmemcpy(card_data-\u003eusb_rx_leftover + usb_rx_leftover_len, buf,\n+\t\tmemcpy(card_data-\u003eusb_rx_leftover + usb_rx_leftover_len, buf + pos,\n \t\t       remaining_bytes);\n \t\tpos += remaining_bytes;\n \n \t\tif (remaining_bytes + usb_rx_leftover_len == cmd_len) {\n+\t\t\tif (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {\n+\t\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\n+\t\t\t\tcard_data-\u003eusb_rx_leftover_len = 0;\n+\t\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\n+\t\t\t\treturn;\n+\t\t\t}\n+\n \t\t\tkvaser_usb_hydra_handle_cmd(dev, cmd);\n \t\t\tusb_rx_leftover_len = 0;\n \t\t} else {\n@@ -2152,11 +2234,17 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,\n \tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\n \n \twhile (pos \u003c len) {\n+\t\tint err;\n+\n \t\tcmd = buf + pos;\n \n-\t\tcmd_len = kvaser_usb_hydra_cmd_size(cmd);\n+\t\terr = kvaser_usb_hydra_cmd_size_rx(cmd, len - pos, \u0026cmd_len);\n+\t\tif (err \u0026\u0026 err != -EAGAIN) {\n+\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\n+\t\t\treturn;\n+\t\t}\n \n-\t\tif (pos + cmd_len \u003e len) {\n+\t\tif (err == -EAGAIN || pos + cmd_len \u003e len) {\n \t\t\t/* We got first part of a command */\n \t\t\tint leftover_bytes;\n \n@@ -2174,6 +2262,11 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,\n \t\t\tbreak;\n \t\t}\n \n+\t\tif (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {\n+\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\n+\t\t\treturn;\n+\t\t}\n+\n \t\tkvaser_usb_hydra_handle_cmd(dev, cmd);\n \t\tpos += cmd_len;\n \t}\n@@ -2203,7 +2296,6 @@ const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = {\n \t.dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming,\n \t.dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams,\n \t.dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter,\n-\t.dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints,\n \t.dev_init_card = kvaser_usb_hydra_init_card,\n \t.dev_init_channel = kvaser_usb_hydra_init_channel,\n \t.dev_get_software_info = kvaser_usb_hydra_get_software_info,\ndiff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c\nindex a876c7819b81c..00302b5c6223e 100644\n--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c\n+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c\n@@ -1964,22 +1964,6 @@ static int kvaser_usb_leaf_get_berr_counter(const struct net_device *netdev,\n \treturn 0;\n }\n \n-static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)\n-{\n-\tstruct usb_host_interface *iface_desc;\n-\tint ret;\n-\n-\tiface_desc = dev-\u003eintf-\u003ecur_altsetting;\n-\n-\t/* use first bulk endpoint for in and out */\n-\tret = usb_find_common_endpoints(iface_desc, \u0026dev-\u003ebulk_in, \u0026dev-\u003ebulk_out,\n-\t\t\t\t\tNULL, NULL);\n-\tif (ret)\n-\t\treturn -ENODEV;\n-\n-\treturn 0;\n-}\n-\n const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {\n \t.dev_set_mode = kvaser_usb_leaf_set_mode,\n \t.dev_set_bittiming = kvaser_usb_leaf_set_bittiming,\n@@ -1987,7 +1971,6 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {\n \t.dev_set_data_bittiming = NULL,\n \t.dev_get_data_busparams = NULL,\n \t.dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter,\n-\t.dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints,\n \t.dev_init_card = kvaser_usb_leaf_init_card,\n \t.dev_init_channel = kvaser_usb_leaf_init_channel,\n \t.dev_remove_channel = kvaser_usb_leaf_remove_channel,\ndiff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c\nindex f72e0644c5fdb..6b088a05a901e 100644\n--- a/drivers/net/can/usb/ucan.c\n+++ b/drivers/net/can/usb/ucan.c\n@@ -61,7 +61,7 @@\n  *    the following way:\n  *\n  *\tm[n].len \u003c=\u003e the length if message n(including the header in bytes)\n- *\tm[n] is is aligned to a 4 byte boundary, hence\n+ *\tm[n] is aligned to a 4 byte boundary, hence\n  *\t  offset(m[0])\t := 0;\n  *\t  offset(m[n+1]) := offset(m[n]) + (m[n].len + 3) \u0026 3\n  *\ndiff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c\nindex 43d7f22820b88..52661e0882054 100644\n--- a/drivers/net/can/xilinx_can.c\n+++ b/drivers/net/can/xilinx_can.c\n@@ -157,6 +157,7 @@ enum xcan_reg {\n #define XCAN_2_FSR_RI_MASK\t\t0x0000003F /* RX Read Index */\n #define XCAN_DLCR_EDL_MASK\t\t0x08000000 /* EDL Mask in DLC */\n #define XCAN_DLCR_BRS_MASK\t\t0x04000000 /* BRS Mask in DLC */\n+#define XCAN_DLCR_ESI_MASK\t\t0x02000000 /* ESI Mask in DLC */\n #define XCAN_ECC_CFG_REECRX_MASK\tBIT(2) /* Reset RX FIFO ECC error counters */\n #define XCAN_ECC_CFG_REECTXOL_MASK\tBIT(1) /* Reset TXOL FIFO ECC error counters */\n #define XCAN_ECC_CFG_REECTXTL_MASK\tBIT(0) /* Reset TXTL FIFO ECC error counters */\n@@ -959,6 +960,11 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base)\n \n \t/* Check the frame received is FD or not*/\n \tif (dlc \u0026 XCAN_DLCR_EDL_MASK) {\n+\t\tif (dlc \u0026 XCAN_DLCR_BRS_MASK)\n+\t\t\tcf-\u003eflags |= CANFD_BRS;\n+\t\tif (dlc \u0026 XCAN_DLCR_ESI_MASK)\n+\t\t\tcf-\u003eflags |= CANFD_ESI;\n+\n \t\tfor (i = 0; i \u003c cf-\u003elen; i += 4) {\n \t\t\tdw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) +\n \t\t\t\t\t(dwindex * XCANFD_DW_BYTES);\ndiff --git a/include/linux/can/core.h b/include/linux/can/core.h\nindex 2de74c2b78b6c..effb5c31ef401 100644\n--- a/include/linux/can/core.h\n+++ b/include/linux/can/core.h\n@@ -51,7 +51,7 @@ extern void can_proto_unregister(const struct can_proto *cp);\n int can_rx_register(struct net *net, struct net_device *dev,\n \t\t    canid_t can_id, canid_t mask,\n \t\t    void (*func)(struct sk_buff *, void *),\n-\t\t    void *data, char *ident, struct sock *sk);\n+\t\t    void *data, u64 ino, struct sock *sk);\n \n extern void can_rx_unregister(struct net *net, struct net_device *dev,\n \t\t\t      canid_t can_id, canid_t mask,\ndiff --git a/include/linux/can/dev.h b/include/linux/can/dev.h\nindex 6d0710d6f571d..346faddee02eb 100644\n--- a/include/linux/can/dev.h\n+++ b/include/linux/can/dev.h\n@@ -176,7 +176,7 @@ static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *s\n \treturn can_dropped_invalid_skb(dev, skb);\n \n invalid_skb:\n-\tkfree_skb(skb);\n+\tdev_kfree_skb_any(skb);\n \tdev-\u003estats.tx_dropped++;\n \treturn true;\n }\ndiff --git a/include/linux/can/skb.h b/include/linux/can/skb.h\nindex 5d27843862fca..87ace09c0d8bd 100644\n--- a/include/linux/can/skb.h\n+++ b/include/linux/can/skb.h\n@@ -78,12 +78,12 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)\n \n \tnskb = skb_clone(skb, GFP_ATOMIC);\n \tif (unlikely(!nskb)) {\n-\t\tkfree_skb(skb);\n+\t\tdev_kfree_skb_any(skb);\n \t\treturn NULL;\n \t}\n \n \tcan_skb_set_owner(nskb, skb-\u003esk);\n-\tconsume_skb(skb);\n+\tdev_consume_skb_any(skb);\n \treturn nskb;\n }\n \ndiff --git a/net/can/af_can.c b/net/can/af_can.c\nindex 34fe3b28d576f..d97f85fc3232d 100644\n--- a/net/can/af_can.c\n+++ b/net/can/af_can.c\n@@ -226,7 +226,7 @@ int can_send(struct sk_buff *skb, int loop)\n \t\tgoto inval_skb;\n \t}\n \n-\tif (unlikely(skb-\u003edev-\u003etype != ARPHRD_CAN)) {\n+\tif (unlikely(!can_get_ml_priv(skb-\u003edev))) {\n \t\terr = -EPERM;\n \t\tgoto inval_skb;\n \t}\n@@ -418,7 +418,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,\n  * @mask: CAN mask (see description)\n  * @func: callback function on filter match\n  * @data: returned parameter for callback function\n- * @ident: string for calling module identification\n+ * @ino: inode number of sock (0 = unknown)\n  * @sk: socket pointer (might be NULL)\n  *\n  * Description:\n@@ -443,7 +443,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,\n  */\n int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,\n \t\t    canid_t mask, void (*func)(struct sk_buff *, void *),\n-\t\t    void *data, char *ident, struct sock *sk)\n+\t\t    void *data, u64 ino, struct sock *sk)\n {\n \tstruct receiver *rcv;\n \tstruct hlist_head *rcv_list;\n@@ -452,7 +452,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,\n \n \t/* insert new receiver  (dev,canid,mask) -\u003e (func,data) */\n \n-\tif (dev \u0026\u0026 (dev-\u003etype != ARPHRD_CAN || !can_get_ml_priv(dev)))\n+\tif (dev \u0026\u0026 !can_get_ml_priv(dev))\n \t\treturn -ENODEV;\n \n \tif (dev \u0026\u0026 !net_eq(net, dev_net(dev)))\n@@ -472,7 +472,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,\n \tatomic_long_set(\u0026rcv-\u003ematches, 0);\n \trcv-\u003efunc = func;\n \trcv-\u003edata = data;\n-\trcv-\u003eident = ident;\n+\trcv-\u003eino = ino;\n \trcv-\u003esk = sk;\n \n \thlist_add_head_rcu(\u0026rcv-\u003elist, rcv_list);\n@@ -519,7 +519,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,\n \tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\n \tstruct can_dev_rcv_lists *dev_rcv_lists;\n \n-\tif (dev \u0026\u0026 dev-\u003etype != ARPHRD_CAN)\n+\tif (dev \u0026\u0026 !can_get_ml_priv(dev))\n \t\treturn;\n \n \tif (dev \u0026\u0026 !net_eq(net, dev_net(dev)))\n@@ -684,8 +684,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,\n {\n \tstruct can_skb_ext *csx = can_skb_ext_find(skb);\n \n-\tif (unlikely(dev-\u003etype != ARPHRD_CAN || !can_get_ml_priv(dev) ||\n-\t\t     !csx || !can_is_can_skb(skb))) {\n+\tif (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_can_skb(skb))) {\n \t\tpr_warn_once(\"PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\\n\",\n \t\t\t     dev-\u003etype, skb-\u003elen);\n \n@@ -710,8 +709,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,\n {\n \tstruct can_skb_ext *csx = can_skb_ext_find(skb);\n \n-\tif (unlikely(dev-\u003etype != ARPHRD_CAN || !can_get_ml_priv(dev) ||\n-\t\t     !csx || !can_is_canfd_skb(skb))) {\n+\tif (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canfd_skb(skb))) {\n \t\tpr_warn_once(\"PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\\n\",\n \t\t\t     dev-\u003etype, skb-\u003elen);\n \n@@ -736,8 +734,7 @@ static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,\n {\n \tstruct can_skb_ext *csx = can_skb_ext_find(skb);\n \n-\tif (unlikely(dev-\u003etype != ARPHRD_CAN || !can_get_ml_priv(dev) ||\n-\t\t     !csx || !can_is_canxl_skb(skb))) {\n+\tif (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canxl_skb(skb))) {\n \t\tpr_warn_once(\"PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\\n\",\n \t\t\t     dev-\u003etype, skb-\u003elen);\n \ndiff --git a/net/can/af_can.h b/net/can/af_can.h\nindex 87887014f5628..6e593ed5db5f0 100644\n--- a/net/can/af_can.h\n+++ b/net/can/af_can.h\n@@ -55,7 +55,7 @@ struct receiver {\n \tatomic_long_t matches;\n \tvoid (*func)(struct sk_buff *skb, void *data);\n \tvoid *data;\n-\tchar *ident;\n+\tu64 ino;\n \tstruct sock *sk;\n \tstruct rcu_head rcu;\n };\ndiff --git a/net/can/bcm.c b/net/can/bcm.c\nindex 3d637a1e0ac1a..301920011a300 100644\n--- a/net/can/bcm.c\n+++ b/net/can/bcm.c\n@@ -54,6 +54,7 @@\n #include \u003clinux/if_arp.h\u003e\n #include \u003clinux/skbuff.h\u003e\n #include \u003clinux/can.h\u003e\n+#include \u003clinux/can/can-ml.h\u003e\n #include \u003clinux/can/core.h\u003e\n #include \u003clinux/can/skb.h\u003e\n #include \u003clinux/can/bcm.h\u003e\n@@ -220,9 +221,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)\n \tstruct bcm_sock *bo = bcm_sk(sk);\n \tstruct bcm_op *op;\n \n-\tseq_printf(m, \"\u003e\u003e\u003e socket %pK\", sk-\u003esk_socket);\n-\tseq_printf(m, \" / sk %pK\", sk);\n-\tseq_printf(m, \" / bo %pK\", bo);\n+\tseq_printf(m, \"\u003e\u003e\u003e sock inode %s\", bo-\u003eprocname);\n \tseq_printf(m, \" / dropped %lu\", bo-\u003edropped_usr_msgs);\n \tseq_printf(m, \" / bound %s\", bcm_proc_getifname(net, ifname, bo-\u003eifindex));\n \tseq_printf(m, \" \u003c\u003c\u003c\\n\");\n@@ -1536,7 +1535,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,\n \t\t\t\t\t\t      op-\u003ecan_id,\n \t\t\t\t\t\t      REGMASK(op-\u003ecan_id),\n \t\t\t\t\t\t      bcm_rx_handler, op,\n-\t\t\t\t\t\t      \"bcm\", sk);\n+\t\t\t\t\t\t      sock_i_ino(sk), sk);\n \n \t\t\t\t/* keep a tracked reference so that a later\n \t\t\t\t * unregister can safely reach the device even\n@@ -1560,7 +1559,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,\n \t\t} else {\n \t\t\terr = can_rx_register(sock_net(sk), NULL, op-\u003ecan_id,\n \t\t\t\t\t      REGMASK(op-\u003ecan_id),\n-\t\t\t\t\t      bcm_rx_handler, op, \"bcm\", sk);\n+\t\t\t\t\t      bcm_rx_handler, op,\n+\t\t\t\t\t      sock_i_ino(sk), sk);\n \t\t}\n \n \t\tif (err) {\n@@ -1719,7 +1719,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)\n \t\t\t\tgoto out_release;\n \t\t\t}\n \n-\t\t\tif (dev-\u003etype != ARPHRD_CAN) {\n+\t\t\tif (!can_get_ml_priv(dev)) {\n \t\t\t\tdev_put(dev);\n \t\t\t\tret = -ENODEV;\n \t\t\t\tgoto out_release;\n@@ -1867,7 +1867,7 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg,\n {\n \tstruct net_device *dev = netdev_notifier_info_to_dev(ptr);\n \n-\tif (dev-\u003etype != ARPHRD_CAN)\n+\tif (!can_get_ml_priv(dev))\n \t\treturn NOTIFY_DONE;\n \tif (msg != NETDEV_UNREGISTER \u0026\u0026 msg != NETDEV_DOWN)\n \t\treturn NOTIFY_DONE;\n@@ -1926,21 +1926,19 @@ static int bcm_release(struct socket *sock)\n \n \t/* remove bcm_ops, timer, rx_unregister(), etc. */\n \n-\tspin_lock(\u0026bcm_notifier_lock);\n-\twhile (bcm_busy_notifier == bo) {\n-\t\tspin_unlock(\u0026bcm_notifier_lock);\n-\t\tschedule_timeout_uninterruptible(1);\n-\t\tspin_lock(\u0026bcm_notifier_lock);\n-\t}\n-\tlist_del(\u0026bo-\u003enotifier);\n-\tspin_unlock(\u0026bcm_notifier_lock);\n-\n+\t/* Remove the procfs entry and the tx_ops before taking RTNL:\n+\t * remove_proc_entry() waits for concurrent readers of the entry and\n+\t * must not hold up RTNL for them. Clear bo-\u003ebcm_proc_read so that\n+\t * bcm_notify() does not remove the entry a second time.\n+\t */\n \tlock_sock(sk);\n \n #if IS_ENABLED(CONFIG_PROC_FS)\n \t/* remove procfs entry */\n-\tif (net-\u003ecan.bcmproc_dir \u0026\u0026 bo-\u003ebcm_proc_read)\n+\tif (net-\u003ecan.bcmproc_dir \u0026\u0026 bo-\u003ebcm_proc_read) {\n \t\tremove_proc_entry(bo-\u003eprocname, net-\u003ecan.bcmproc_dir);\n+\t\tbo-\u003ebcm_proc_read = NULL;\n+\t}\n #endif /* CONFIG_PROC_FS */\n \n \tlist_for_each_entry_safe(op, next, \u0026bo-\u003etx_ops, list) {\n@@ -1948,6 +1946,21 @@ static int bcm_release(struct socket *sock)\n \t\tbcm_remove_op(op);\n \t}\n \n+\trelease_sock(sk);\n+\n+\trtnl_lock();\n+\n+\t/* The netdev notifier chain runs under RTNL, so bcm_notifier() can't\n+\t * be walking bcm_notifier_list and point to this socket. The spinlock\n+\t * is still needed as bcm_init() adds sockets without holding RTNL.\n+\t */\n+\tspin_lock(\u0026bcm_notifier_lock);\n+\tWARN_ON_ONCE(bcm_busy_notifier == bo);\n+\tlist_del(\u0026bo-\u003enotifier);\n+\tspin_unlock(\u0026bcm_notifier_lock);\n+\n+\tlock_sock(sk);\n+\n \tlist_for_each_entry_safe(op, next, \u0026bo-\u003erx_ops, list) {\n \t\t/*\n \t\t * Don't care if we're bound or not (due to netdev problems)\n@@ -1973,6 +1986,8 @@ static int bcm_release(struct socket *sock)\n \n \t}\n \n+\trtnl_unlock();\n+\n \tsynchronize_rcu();\n \n \tlist_for_each_entry_safe(op, next, \u0026bo-\u003erx_ops, list) {\n@@ -2024,7 +2039,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int\n \t\t\tret = -ENODEV;\n \t\t\tgoto fail;\n \t\t}\n-\t\tif (dev-\u003etype != ARPHRD_CAN) {\n+\t\tif (!can_get_ml_priv(dev)) {\n \t\t\tdev_put(dev);\n \t\t\tret = -ENODEV;\n \t\t\tgoto fail;\n@@ -2040,8 +2055,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int\n \n #if IS_ENABLED(CONFIG_PROC_FS)\n \tif (net-\u003ecan.bcmproc_dir) {\n-\t\t/* unique socket address as filename */\n-\t\tsprintf(bo-\u003eprocname, \"%llu\", sock_i_ino(sk));\n+\t\t/* use unique socket inode number as filename */\n+\t\tsnprintf(bo-\u003eprocname, sizeof(bo-\u003eprocname),\n+\t\t\t \"%llu\", sock_i_ino(sk));\n \t\tbo-\u003ebcm_proc_read = proc_create_net_single(bo-\u003eprocname, 0644,\n \t\t\t\t\t\t     net-\u003ecan.bcmproc_dir,\n \t\t\t\t\t\t     bcm_proc_show, sk);\ndiff --git a/net/can/gw.c b/net/can/gw.c\nindex 5793cb2420ed3..8a5327d8a00e8 100644\n--- a/net/can/gw.c\n+++ b/net/can/gw.c\n@@ -52,6 +52,7 @@\n #include \u003clinux/if_arp.h\u003e\n #include \u003clinux/skbuff.h\u003e\n #include \u003clinux/can.h\u003e\n+#include \u003clinux/can/can-ml.h\u003e\n #include \u003clinux/can/core.h\u003e\n #include \u003clinux/can/skb.h\u003e\n #include \u003clinux/can/gw.h\u003e\n@@ -579,7 +580,7 @@ static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)\n {\n \treturn can_rx_register(net, gwj-\u003esrc.dev, gwj-\u003eccgw.filter.can_id,\n \t\t\t       gwj-\u003eccgw.filter.can_mask, can_can_gw_rcv,\n-\t\t\t       gwj, \"gw\", NULL);\n+\t\t\t       gwj, 0, NULL);\n }\n \n static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)\n@@ -612,7 +613,7 @@ static int cgw_notifier(struct notifier_block *nb,\n \tstruct net_device *dev = netdev_notifier_info_to_dev(ptr);\n \tstruct net *net = dev_net(dev);\n \n-\tif (dev-\u003etype != ARPHRD_CAN)\n+\tif (!can_get_ml_priv(dev))\n \t\treturn NOTIFY_DONE;\n \n \tif (msg == NETDEV_UNREGISTER) {\n@@ -1163,7 +1164,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,\n \tif (!gwj-\u003esrc.dev)\n \t\tgoto out;\n \n-\tif (gwj-\u003esrc.dev-\u003etype != ARPHRD_CAN)\n+\tif (!can_get_ml_priv(gwj-\u003esrc.dev))\n \t\tgoto out;\n \n \tgwj-\u003edst.dev = __dev_get_by_index(net, gwj-\u003eccgw.dst_idx);\n@@ -1171,7 +1172,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,\n \tif (!gwj-\u003edst.dev)\n \t\tgoto out;\n \n-\tif (gwj-\u003edst.dev-\u003etype != ARPHRD_CAN)\n+\tif (!can_get_ml_priv(gwj-\u003edst.dev))\n \t\tgoto out;\n \n \t/* is sending the skb back to the incoming interface intended? */\ndiff --git a/net/can/isotp.c b/net/can/isotp.c\nindex f5dc9d04bd686..17ff40a4708db 100644\n--- a/net/can/isotp.c\n+++ b/net/can/isotp.c\n@@ -65,6 +65,7 @@\n #include \u003clinux/if_arp.h\u003e\n #include \u003clinux/skbuff.h\u003e\n #include \u003clinux/can.h\u003e\n+#include \u003clinux/can/can-ml.h\u003e\n #include \u003clinux/can/core.h\u003e\n #include \u003clinux/can/skb.h\u003e\n #include \u003clinux/can/isotp.h\u003e\n@@ -755,6 +756,14 @@ static void isotp_rcv(struct sk_buff *skb, void *data)\n \tif (skb-\u003elen != so-\u003ell.mtu)\n \t\treturn;\n \n+\t/* check for correct CAN CC/FD frame content */\n+\tif (so-\u003ell.mtu == CAN_MTU) {\n+\t\tif (!can_is_can_skb(skb))\n+\t\t\treturn;\n+\t} else if (!can_is_canfd_skb(skb)) {\n+\t\treturn;\n+\t}\n+\n \tcf = (struct canfd_frame *)skb-\u003edata;\n \n \t/* if enabled: check reception of my configured extended address */\n@@ -1479,16 +1488,17 @@ static int isotp_release(struct socket *sock)\n \t/* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */\n \twake_up_interruptible(\u0026so-\u003ewait);\n \n+\trtnl_lock();\n+\n+\t/* The netdev notifier chain runs under RTNL, so isotp_notifier() can't\n+\t * be walking isotp_notifier_list and point to this socket. The spinlock\n+\t * is still needed as isotp_init() adds sockets without holding RTNL.\n+\t */\n \tspin_lock(\u0026isotp_notifier_lock);\n-\twhile (isotp_busy_notifier == so) {\n-\t\tspin_unlock(\u0026isotp_notifier_lock);\n-\t\tschedule_timeout_uninterruptible(1);\n-\t\tspin_lock(\u0026isotp_notifier_lock);\n-\t}\n+\tWARN_ON_ONCE(isotp_busy_notifier == so);\n \tlist_del(\u0026so-\u003enotifier);\n \tspin_unlock(\u0026isotp_notifier_lock);\n \n-\trtnl_lock();\n \tlock_sock(sk);\n \n \t/* remove current filters \u0026 unregister\n@@ -1496,11 +1506,11 @@ static int isotp_release(struct socket *sock)\n \t */\n \tif (so-\u003ebound \u0026\u0026 so-\u003edev) {\n \t\tif (isotp_register_rxid(so))\n-\t\t\tcan_rx_unregister(net, so-\u003edev, so-\u003erxid,\n+\t\t\tcan_rx_unregister(dev_net(so-\u003edev), so-\u003edev, so-\u003erxid,\n \t\t\t\t\t  SINGLE_MASK(so-\u003erxid),\n \t\t\t\t\t  isotp_rcv, sk);\n \n-\t\tcan_rx_unregister(net, so-\u003edev, so-\u003etxid,\n+\t\tcan_rx_unregister(dev_net(so-\u003edev), so-\u003edev, so-\u003etxid,\n \t\t\t\t  SINGLE_MASK(so-\u003etxid),\n \t\t\t\t  isotp_rcv_echo, sk);\n \t\tnetdev_put(so-\u003edev, \u0026so-\u003edev_tracker);\n@@ -1610,7 +1620,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l\n \t\terr = -ENODEV;\n \t\tgoto out;\n \t}\n-\tif (dev-\u003etype != ARPHRD_CAN) {\n+\tif (!can_get_ml_priv(dev)) {\n \t\terr = -ENODEV;\n \t\tgoto out_put_dev;\n \t}\n@@ -1625,14 +1635,14 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l\n \n \tif (isotp_register_rxid(so))\n \t\tcan_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),\n-\t\t\t\tisotp_rcv, sk, \"isotp\", sk);\n+\t\t\t\tisotp_rcv, sk, sock_i_ino(sk), sk);\n \n \t/* no consecutive frame echo skb in flight */\n \tWRITE_ONCE(so-\u003ecfecho, 0);\n \n \t/* register for echo skb's */\n \tcan_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),\n-\t\t\tisotp_rcv_echo, sk, \"isotpe\", sk);\n+\t\t\tisotp_rcv_echo, sk, sock_i_ino(sk), sk);\n \n \t/* switch to new settings */\n \tso-\u003eifindex = ifindex;\n@@ -1897,7 +1907,7 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,\n {\n \tstruct net_device *dev = netdev_notifier_info_to_dev(ptr);\n \n-\tif (dev-\u003etype != ARPHRD_CAN)\n+\tif (!can_get_ml_priv(dev))\n \t\treturn NOTIFY_DONE;\n \tif (msg != NETDEV_UNREGISTER \u0026\u0026 msg != NETDEV_DOWN)\n \t\treturn NOTIFY_DONE;\ndiff --git a/net/can/j1939/main.c b/net/can/j1939/main.c\nindex 5e5e6c228f225..d9384cf0e356f 100644\n--- a/net/can/j1939/main.c\n+++ b/net/can/j1939/main.c\n@@ -184,7 +184,7 @@ static int j1939_can_rx_register(struct j1939_priv *priv)\n \n \tj1939_priv_get(priv);\n \tret = can_rx_register(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,\n-\t\t\t      j1939_can_recv, priv, \"j1939\", NULL);\n+\t\t\t      j1939_can_recv, priv, 0, NULL);\n \tif (ret \u003c 0) {\n \t\tj1939_priv_put(priv);\n \t\treturn ret;\ndiff --git a/net/can/proc.c b/net/can/proc.c\nindex de4d05ae34597..64994ab485414 100644\n--- a/net/can/proc.c\n+++ b/net/can/proc.c\n@@ -76,16 +76,39 @@ static const char rx_list_name[][8] = {\n  * af_can statistics stuff\n  */\n \n+static void can_reset_pkg_stats(struct can_pkg_stats *pkg_stats)\n+{\n+\tatomic_long_set(\u0026pkg_stats-\u003erx_frames, 0);\n+\tatomic_long_set(\u0026pkg_stats-\u003etx_frames, 0);\n+\tatomic_long_set(\u0026pkg_stats-\u003ematches, 0);\n+\n+\tpkg_stats-\u003etotal_rx_rate = 0;\n+\tpkg_stats-\u003etotal_tx_rate = 0;\n+\tpkg_stats-\u003etotal_rx_match_ratio = 0;\n+\n+\tpkg_stats-\u003ecurrent_rx_rate = 0;\n+\tpkg_stats-\u003ecurrent_tx_rate = 0;\n+\tpkg_stats-\u003ecurrent_rx_match_ratio = 0;\n+\n+\tpkg_stats-\u003emax_rx_rate = 0;\n+\tpkg_stats-\u003emax_tx_rate = 0;\n+\tpkg_stats-\u003emax_rx_match_ratio = 0;\n+\n+\tatomic_long_set(\u0026pkg_stats-\u003erx_frames_delta, 0);\n+\tatomic_long_set(\u0026pkg_stats-\u003etx_frames_delta, 0);\n+\tatomic_long_set(\u0026pkg_stats-\u003ematches_delta, 0);\n+}\n+\n static void can_init_stats(struct net *net)\n {\n \tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\n \tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\n \t/*\n-\t * This memset function is called from a timer context (when\n+\t * This stats reset is called from a timer context (when\n \t * can_stattimer is active which is the default) OR in a process\n \t * context (reading the proc_fs when can_stattimer is disabled).\n \t */\n-\tmemset(pkg_stats, 0, sizeof(struct can_pkg_stats));\n+\tcan_reset_pkg_stats(pkg_stats);\n \tpkg_stats-\u003ejiffies_init = jiffies;\n \n \trcv_lists_stats-\u003estats_reset++;\n@@ -192,25 +215,27 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,\n \n \thlist_for_each_entry_rcu(r, rx_list, list) {\n \t\tchar *fmt = (r-\u003ecan_id \u0026 CAN_EFF_FLAG)?\n-\t\t\t\"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\\n\" :\n-\t\t\t\"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\\n\";\n+\t\t\t\"  %6s  %08x  %08x  %8ld  %10llu\" :\n+\t\t\t\"  %6s     %03x    %08x  %8ld  %10llu\";\n \n \t\tseq_printf(m, fmt, DNAME(dev), r-\u003ecan_id, r-\u003emask,\n-\t\t\t   r-\u003efunc, r-\u003edata, atomic_long_read(\u0026r-\u003ematches),\n-\t\t\t   r-\u003eident);\n+\t\t\t   atomic_long_read(\u0026r-\u003ematches), r-\u003eino);\n+\n+\t\t/* without kallsyms %ps would print the raw text address */\n+\t\tif (IS_ENABLED(CONFIG_KALLSYMS))\n+\t\t\tseq_printf(m, \"  %ps\\n\", r-\u003efunc);\n+\t\telse\n+\t\t\tseq_puts(m, \"  (unknown)\\n\");\n \t}\n }\n \n static void can_print_recv_banner(struct seq_file *m)\n {\n \t/*\n-\t *                  can1.  00000000  00000000  00000000\n-\t *                 .......          0  tp20\n+\t *    device   can_id   can_mask   matches  sock_inode  function\n+\t *     vcan0     000    00000000         0       43798  raw_rcv [can_raw]\n \t */\n-\tif (IS_ENABLED(CONFIG_64BIT))\n-\t\tseq_puts(m, \"  device   can_id   can_mask      function          userdata       matches  ident\\n\");\n-\telse\n-\t\tseq_puts(m, \"  device   can_id   can_mask  function  userdata   matches  ident\\n\");\n+\tseq_puts(m, \"  device   can_id   can_mask   matches  sock_inode  function\\n\");\n }\n \n static int can_stats_proc_show(struct seq_file *m, void *v)\ndiff --git a/net/can/raw.c b/net/can/raw.c\nindex 0acd4f6c6dd67..d95ce54a4c458 100644\n--- a/net/can/raw.c\n+++ b/net/can/raw.c\n@@ -226,7 +226,7 @@ static int raw_enable_filters(struct net *net, struct net_device *dev,\n \tfor (i = 0; i \u003c count; i++) {\n \t\terr = can_rx_register(net, dev, filter[i].can_id,\n \t\t\t\t      filter[i].can_mask,\n-\t\t\t\t      raw_rcv, sk, \"raw\", sk);\n+\t\t\t\t      raw_rcv, sk, sock_i_ino(sk), sk);\n \t\tif (err) {\n \t\t\t/* clean up successfully registered filters */\n \t\t\twhile (--i \u003e= 0)\n@@ -247,7 +247,7 @@ static int raw_enable_errfilter(struct net *net, struct net_device *dev,\n \n \tif (err_mask)\n \t\terr = can_rx_register(net, dev, 0, err_mask | CAN_ERR_FLAG,\n-\t\t\t\t      raw_rcv, sk, \"raw\", sk);\n+\t\t\t\t      raw_rcv, sk, sock_i_ino(sk), sk);\n \n \treturn err;\n }\n@@ -348,7 +348,7 @@ static int raw_notifier(struct notifier_block *nb, unsigned long msg,\n {\n \tstruct net_device *dev = netdev_notifier_info_to_dev(ptr);\n \n-\tif (dev-\u003etype != ARPHRD_CAN)\n+\tif (!can_get_ml_priv(dev))\n \t\treturn NOTIFY_DONE;\n \tif (msg != NETDEV_UNREGISTER \u0026\u0026 msg != NETDEV_DOWN)\n \t\treturn NOTIFY_DONE;\n@@ -422,16 +422,17 @@ static int raw_release(struct socket *sock)\n \tro = raw_sk(sk);\n \tnet = sock_net(sk);\n \n+\trtnl_lock();\n+\n+\t/* The netdev notifier chain runs under RTNL, so raw_notifier() can't\n+\t * be walking raw_notifier_list and point to this socket. The spinlock\n+\t * is still needed as raw_init() adds sockets without holding RTNL.\n+\t */\n \tspin_lock(\u0026raw_notifier_lock);\n-\twhile (raw_busy_notifier == ro) {\n-\t\tspin_unlock(\u0026raw_notifier_lock);\n-\t\tschedule_timeout_uninterruptible(1);\n-\t\tspin_lock(\u0026raw_notifier_lock);\n-\t}\n+\tWARN_ON_ONCE(raw_busy_notifier == ro);\n \tlist_del(\u0026ro-\u003enotifier);\n \tspin_unlock(\u0026raw_notifier_lock);\n \n-\trtnl_lock();\n \tlock_sock(sk);\n \n \t/* remove current filters \u0026 unregister */\n@@ -491,7 +492,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len\n \t\t\terr = -ENODEV;\n \t\t\tgoto out;\n \t\t}\n-\t\tif (dev-\u003etype != ARPHRD_CAN) {\n+\t\tif (!can_get_ml_priv(dev)) {\n \t\t\terr = -ENODEV;\n \t\t\tgoto out_put_dev;\n \t\t}\n@@ -529,8 +530,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len\n \t\tro-\u003ebound = 1;\n \t\t/* bind() ok -\u003e hold a reference for new ro-\u003edev */\n \t\tro-\u003edev = dev;\n-\t\tif (ro-\u003edev)\n-\t\t\tnetdev_hold(ro-\u003edev, \u0026ro-\u003edev_tracker, GFP_KERNEL);\n+\t\tnetdev_hold(ro-\u003edev, \u0026ro-\u003edev_tracker, GFP_KERNEL);\n \t}\n \n out_put_dev:\n"
}

2/1 2026/10/15 04:32 agent patch-evaluator
4m Model:
core

Args:
null

Results:
{
  "EnableConfigs": [
    "CAN",
    "CAN_RAW",
    "CAN_BCM",
    "CAN_ISOTP",
    "CAN_GW",
    "CAN_DEV",
    "CAN_VCAN",
    "CAN_KVASER_USB",
    "PROC_FS"
  ],
  "FocusSymbols": [
    "bcm_release",
    "raw_release",
    "isotp_release",
    "isotp_rcv",
    "isotp_bind",
    "bcm_rx_setup",
    "raw_enable_filters",
    "can_rx_register",
    "can_rx_unregister",
    "can_send",
    "can_rcv",
    "canfd_rcv",
    "canxl_rcv",
    "can_dropped_invalid_skb",
    "can_put_echo_skb",
    "cgw_create_job",
    "kvaser_usb_hydra_read_bulk_callback"
  ],
  "Reasoning": "The patch series introduces significant changes and refactorings across the CAN core networking subsystem (net/can/) and CAN device drivers:\n1. Socket release \u0026 notifier concurrency refactoring: In bcm_release(), isotp_release(), and raw_release(), socket locking and notifier list removal were overhauled to serialize under RTNL, removing busy-wait loops and adding new WARN_ON_ONCE() runtime assertions to verify that notifiers are not concurrently executing on the socket being destroyed.\n2. Device validation: Checks for CAN device capability and mid-layer priv (can_get_ml_priv(dev)) replace ARPHRD_CAN checks across af_can, bcm, raw, isotp, and gw.\n3. Protocol and SKB handling: Added CAN-XL capability validation in can_dropped_invalid_skb(), updated frame content checking in isotp_rcv(), and improved bounds checking/skb freeing in can_put_echo_skb().\n4. USB driver packet parsing: In kvaser_usb_hydra, command size parsing and verification were overhauled to handle partial commands and validate command bounds.\n\nAll modified networking code is fully reachable in virtualized QEMU environments using standard CAN sockets (CAN_RAW, CAN_BCM, CAN_ISOTP), virtual netdevs (vcan), and USB fuzzing interfaces. Fuzzing is warranted to test the new locking invariants, assertions, and boundary checks.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit e266d8df68870dedf5e7f9fa0d4a7c435ea59542
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Oct 15 04:32:17 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml b/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml
new file mode 100644
index 0000000000000..d5cba5b1bac19
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/can/aeroflexgaisler,grcan.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aeroflex Gaisler GRCAN and GRHCAN CAN controllers
+
+maintainers:
+  - Marc Kleine-Budde <mkl@pengutronix.de>
+
+description: |
+  The GRCAN and GRHCAN CAN controllers are available in the GRLIB VHDL IP
+  core library.
+
+  On a LEON SPARC system there are no device tree source files. The nodes
+  are built by the PROM from the AMBA plug&play information, which does not
+  provide a compatible string. The driver therefore matches on the node
+  name, which is built as "<core name>@<irq>,<address>" from the "name" and
+  "reg" properties of the AMBA plug&play core.
+
+  The GRLIB build ID is not a property of the controller node either. It is
+  read from the "systemid" property of the "/ambapp0" node, and the TX bug
+  workaround is enabled when that property is absent or when its least
+  significant 16 bits are smaller than 4100.
+
+select:
+  properties:
+    $nodename:
+      pattern: '^(01_034|01_03d|GAISLER_GRCAN|GAISLER_GRHCAN)@'
+  required:
+    - $nodename
+
+properties:
+  reg:
+    maxItems: 1
+
+  freq:
+    description:
+      Frequency of the external oscillator clock in Hz, which is the
+      frequency of the AMBA bus in the ordinary case.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  interrupts:
+    maxItems: 1
+    description:
+      Interrupt number of the controller, as built from the AMBA plug&play
+      information.
+
+required:
+  - reg
+  - freq
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    /* AMBA plug&play children are named "<core name>@<irq>,<address>" */
+    GAISLER_GRCAN@c,80000000 {
+        reg = <0x80000000 0x1000>;
+        freq = <40000000>;
+        interrupts = <12>;
+    };
+...
diff --git a/Documentation/devicetree/bindings/net/can/grcan.txt b/Documentation/devicetree/bindings/net/can/grcan.txt
deleted file mode 100644
index 34ef3498f8870..0000000000000
--- a/Documentation/devicetree/bindings/net/can/grcan.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-Aeroflex Gaisler GRCAN and GRHCAN CAN controllers.
-
-The GRCAN and CRHCAN CAN controllers are available in the GRLIB VHDL IP core
-library.
-
-Note: These properties are built from the AMBA plug&play in a Leon SPARC system
-(the ordinary environment for GRCAN and GRHCAN). There are no dts files for
-sparc.
-
-Required properties:
-
-- name : Should be "GAISLER_GRCAN", "01_03d", "GAISLER_GRHCAN" or "01_034"
-
-- reg : Address and length of the register set for the device
-
-- freq : Frequency of the external oscillator clock in Hz (the frequency of
-	the amba bus in the ordinary case)
-
-- interrupts : Interrupt number for this device
-
-Optional properties:
-
-- systemid : If not present or if the value of the least significant 16 bits
-	of this 32-bit property is smaller than GRCAN_TXBUG_SAFE_GRLIB_VERSION
-	a bug workaround is activated.
-
-For further information look in the documentation for the GLIB IP core library:
-http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
index b9d9dd7a79676..4b94bc8d911be 100644
--- a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
@@ -13,6 +13,8 @@ properties:
   compatible:
     oneOf:
       - enum:
+          - renesas,r9a08g045-canfd        # RZ/G3S
+          - renesas,r9a08g046-canfd        # RZ/G3L
           - renesas,r9a09g047-canfd        # RZ/G3E
           - renesas,r9a09g077-canfd        # RZ/T2H
 
@@ -132,7 +134,9 @@ properties:
   power-domains:
     maxItems: 1
 
-  resets: true
+  resets:
+    minItems: 1
+    maxItems: 2
 
   reset-names:
     items:
@@ -185,8 +189,6 @@ required:
   - clocks
   - clock-names
   - power-domains
-  - assigned-clocks
-  - assigned-clock-rates
   - channel0
   - channel1
 
@@ -198,6 +200,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - renesas,r9a08g045-canfd
               - renesas,rzg2l-canfd
     then:
       properties:
@@ -209,7 +212,6 @@ allOf:
 
         resets:
           minItems: 2
-          maxItems: 2
 
   - if:
       properties:
@@ -231,6 +233,8 @@ allOf:
         resets:
           maxItems: 1
 
+        reset-names: false
+
   - if:
       properties:
         compatible:
@@ -246,7 +250,6 @@ allOf:
 
         resets:
           minItems: 2
-          maxItems: 2
 
   - if:
       properties:
@@ -266,6 +269,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - renesas,r9a08g045-canfd
               - renesas,r9a09g077-canfd
               - renesas,rcar-gen3-canfd
               - renesas,rzg2l-canfd
@@ -291,6 +295,25 @@ allOf:
       patternProperties:
         "^channel[6-7]$": false
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: renesas,r9a08g046-canfd
+    then:
+      properties:
+        interrupts:
+          minItems: 11
+
+        interrupt-names:
+          minItems: 11
+
+        resets:
+          minItems: 2
+
+      patternProperties:
+        "^channel[3-7]$": false
+
   - if:
       properties:
         compatible:
@@ -330,6 +353,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - renesas,r9a08g045-canfd
               - renesas,r9a09g047-canfd
               - renesas,rzg2l-canfd
     then:
@@ -350,6 +374,22 @@ allOf:
       properties:
         reset-names: false
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - renesas,r9a08g045-canfd
+              - renesas,r9a08g046-canfd
+    then:
+      properties:
+        renesas,no-can-fd: false
+        renesas,fd-only: false
+    else:
+      required:
+        - assigned-clocks
+        - assigned-clock-rates
+
 unevaluatedProperties: false
 
 examples:
diff --git a/Documentation/networking/can.rst b/Documentation/networking/can.rst
index 536ff411da1d1..908c199cf6ada 100644
--- a/Documentation/networking/can.rst
+++ b/Documentation/networking/can.rst
@@ -1040,17 +1040,17 @@ As described in :ref:`socketcan-receive-lists` the SocketCAN core uses several f
 lists to deliver received CAN frames to CAN protocol modules. These
 receive lists, their filters and the count of filter matches can be
 checked in the appropriate receive list. All entries contain the
-device and a protocol module identifier::
+CAN network device and the subscribed function name::
 
     foo@bar:~$ cat /proc/net/can/rcvlist_all
 
     receive list 'rx_all':
-      (vcan3: no entry)
-      (vcan2: no entry)
-      (vcan1: no entry)
-      device   can_id   can_mask  function  userdata   matches  ident
-       vcan0     000    00000000  f88e6370  f6c6f400         0  raw
       (any: no entry)
+      device   can_id   can_mask   matches  sock_inode  function
+       vcan0     000    00000000         0       63586  raw_rcv [can_raw]
+      (vcan1: no entry)
+      (vcan2: no entry)
+      (vcan3: no entry)
 
 In this example an application requests any CAN traffic from vcan0::
 
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index a8fad6fe53020..fb16f67a99f99 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -254,7 +254,6 @@ source "drivers/net/can/peak_canfd/Kconfig"
 source "drivers/net/can/rcar/Kconfig"
 source "drivers/net/can/rockchip/Kconfig"
 source "drivers/net/can/sja1000/Kconfig"
-source "drivers/net/can/softing/Kconfig"
 source "drivers/net/can/spi/Kconfig"
 source "drivers/net/can/usb/Kconfig"
 
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 4010d17f85836..fa2cdd7bcd0ac 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -13,7 +13,6 @@ obj-y				+= rcar/
 obj-y				+= rockchip/
 obj-y				+= spi/
 obj-y				+= usb/
-obj-y				+= softing/
 
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_BXCAN)		+= bxcan.o
diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c
index 4bddd015775bc..622c5d73e33a8 100644
--- a/drivers/net/can/bxcan.c
+++ b/drivers/net/can/bxcan.c
@@ -1042,7 +1042,7 @@ static void bxcan_remove(struct platform_device *pdev)
 	free_candev(ndev);
 }
 
-static int __maybe_unused bxcan_suspend(struct device *dev)
+static int bxcan_suspend(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct bxcan_priv *priv = netdev_priv(ndev);
@@ -1059,7 +1059,7 @@ static int __maybe_unused bxcan_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused bxcan_resume(struct device *dev)
+static int bxcan_resume(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct bxcan_priv *priv = netdev_priv(ndev);
@@ -1076,7 +1076,7 @@ static int __maybe_unused bxcan_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume);
 
 static const struct of_device_id bxcan_of_match[] = {
 	{.compatible = "st,stm32f4-bxcan"},
@@ -1087,7 +1087,7 @@ MODULE_DEVICE_TABLE(of, bxcan_of_match);
 static struct platform_driver bxcan_driver = {
 	.driver = {
 		.name = KBUILD_MODNAME,
-		.pm = &bxcan_pm_ops,
+		.pm = pm_sleep_ptr(&bxcan_pm_ops),
 		.of_match_table = bxcan_of_match,
 	},
 	.probe = bxcan_probe,
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index b6c4f02ffb97a..ac81670762c7c 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -137,11 +137,11 @@ static int cc770_get_platform_data(struct platform_device *pdev,
 	struct cc770_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	priv->can.clock.freq = pdata->osc_freq;
+	priv->cpu_interface = pdata->cir;
 	if (priv->cpu_interface & CPUIF_DSC)
 		priv->can.clock.freq /= 2;
 	priv->clkout = pdata->cor;
 	priv->bus_config = pdata->bcr;
-	priv->cpu_interface = pdata->cir;
 
 	return 0;
 }
@@ -156,10 +156,13 @@ static int cc770_platform_probe(struct platform_device *pdev)
 	int err, irq;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!mem || irq <= 0)
+	if (!mem)
 		return -ENODEV;
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
 	mem_size = resource_size(mem);
 	if (!request_mem_region(mem->start, mem_size, pdev->name))
 		return -EBUSY;
diff --git a/drivers/net/can/ctucanfd/ctucanfd.h b/drivers/net/can/ctucanfd/ctucanfd.h
index 0e9904f6a05d6..7dcd7dc507e49 100644
--- a/drivers/net/can/ctucanfd/ctucanfd.h
+++ b/drivers/net/can/ctucanfd/ctucanfd.h
@@ -76,7 +76,7 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr,
 			void (*set_drvdata_fnc)(struct device *dev,
 						struct net_device *ndev));
 
-int ctucan_suspend(struct device *dev) __maybe_unused;
-int ctucan_resume(struct device *dev) __maybe_unused;
+int ctucan_suspend(struct device *dev);
+int ctucan_resume(struct device *dev);
 
 #endif /*__CTUCANFD__*/
diff --git a/drivers/net/can/ctucanfd/ctucanfd_pci.c b/drivers/net/can/ctucanfd/ctucanfd_pci.c
index 4b6db28f7b670..9c9c41c3058c0 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c
@@ -259,7 +259,7 @@ static void ctucan_pci_remove(struct pci_dev *pdev)
 	kfree(bdata);
 }
 
-static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
 
 static const struct pci_device_id ctucan_pci_tbl[] = {
 	{PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21,
@@ -273,7 +273,7 @@ static struct pci_driver ctucan_pci_driver = {
 	.id_table = ctucan_pci_tbl,
 	.probe = ctucan_pci_probe,
 	.remove = ctucan_pci_remove,
-	.driver.pm = &ctucan_pci_pm_ops,
+	.driver.pm = pm_sleep_ptr(&ctucan_pci_pm_ops),
 };
 
 module_pci_driver(ctucan_pci_driver);
diff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c
index 70e2577c85416..4962b00ee8ac0 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_platform.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c
@@ -99,7 +99,7 @@ static void ctucan_platform_remove(struct platform_device *pdev)
 	free_candev(ndev);
 }
 
-static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);
 
 /* Match table for OF platform binding */
 static const struct of_device_id ctucan_of_match[] = {
@@ -114,7 +114,7 @@ static struct platform_driver ctucanfd_driver = {
 	.remove = ctucan_platform_remove,
 	.driver	= {
 		.name = DRV_NAME,
-		.pm = &ctucan_platform_pm_ops,
+		.pm = pm_sleep_ptr(&ctucan_platform_pm_ops),
 		.of_match_table	= ctucan_of_match,
 	},
 };
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 14edec5afb57e..738d5968dfa68 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
  */
 
+#include <linux/can/can-ml.h>
 #include <linux/can/dev.h>
 #include <linux/module.h>
 #include <net/can.h>
@@ -54,6 +55,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 	if (idx >= priv->echo_skb_max) {
 		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
 			   __func__, idx, priv->echo_skb_max);
+		dev_kfree_skb_any(skb);
 		return -EINVAL;
 	}
 
@@ -62,7 +64,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 	    (skb->protocol != htons(ETH_P_CAN) &&
 	     skb->protocol != htons(ETH_P_CANFD) &&
 	     skb->protocol != htons(ETH_P_CANXL))) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return 0;
 	}
 
@@ -90,7 +92,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 	} else {
 		/* locking problem with netif_stop_queue() ?? */
 		netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return -EBUSY;
 	}
 
@@ -227,7 +229,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
 
 	csx = can_skb_ext_add(skb);
 	if (!csx) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		goto out_error_cc;
 	}
 
@@ -258,7 +260,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
 
 	csx = can_skb_ext_add(skb);
 	if (!csx) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		goto out_error_fd;
 	}
 
@@ -296,7 +298,7 @@ struct sk_buff *alloc_canxl_skb(struct net_device *dev,
 
 	csx = can_skb_ext_add(skb);
 	if (!csx) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		goto out_error_xl;
 	}
 
@@ -388,7 +390,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
 		break;
 
 	case ETH_P_CANXL:
-		if (!can_is_canxl_skb(skb))
+		if (!can_cap_enabled(dev, CAN_CAP_XL) || !can_is_canxl_skb(skb))
 			goto inval_skb;
 		break;
 
@@ -402,7 +404,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
 	return false;
 
 inval_skb:
-	kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 	dev->stats.tx_dropped++;
 	return true;
 }
diff --git a/drivers/net/can/esd/esdacc.c b/drivers/net/can/esd/esdacc.c
index 73e66f9a3781c..05d41ed34a02e 100644
--- a/drivers/net/can/esd/esdacc.c
+++ b/drivers/net/can/esd/esdacc.c
@@ -62,14 +62,17 @@ static void acc_resetmode_leave(struct acc_core *core)
 	acc_resetmode_entered(core);
 }
 
-static void acc_txq_put(struct acc_core *core, u32 acc_id, u32 acc_dlc,
-			const void *data)
+static void acc_txq_put(struct acc_core *core, u32 acc_dlc, const void *data)
 {
 	acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_1,
 			   *((const u32 *)(data + 4)));
 	acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_0,
 			   *((const u32 *)data));
 	acc_write32(core, ACC_CORE_OF_TXFIFO_DLC, acc_dlc);
+}
+
+static void acc_txq_start(struct acc_core *core, u32 acc_id)
+{
 	/* CAN id must be written at last. This write starts TX. */
 	acc_write32(core, ACC_CORE_OF_TXFIFO_ID, acc_id);
 }
@@ -287,11 +290,12 @@ netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 		acc_id = cf->can_id & CAN_SFF_MASK;
 	}
 
-	can_put_echo_skb(skb, netdev, core->tx_fifo_head, 0);
+	acc_txq_put(core, acc_dlc, cf->data);
 
+	can_put_echo_skb(skb, netdev, core->tx_fifo_head, 0);
 	core->tx_fifo_head = acc_tx_fifo_next(core, tx_fifo_head);
 
-	acc_txq_put(core, acc_id, acc_dlc, cf->data);
+	acc_txq_start(core, acc_id);
 
 	return NETDEV_TX_OK;
 }
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 86b40abe9e767..30ae7c344a05e 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1986,6 +1986,7 @@ static int flexcan_setup_stop_mode_gpr(struct platform_device *pdev)
 		"gpr %s req_gpr=0x02%x req_bit=%u\n",
 		gpr_np->full_name, priv->stm.req_gpr, priv->stm.req_bit);
 
+	of_node_put(gpr_np);
 	return 0;
 
 out_put_node:
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index ce12fa6df56d5..1b4944d1d06dd 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -10,8 +10,8 @@
  * Full documentation of the GRCAN core can be found here:
  * http://www.gaisler.com/products/grlib/grip.pdf
  *
- * See "Documentation/devicetree/bindings/net/can/grcan.txt" for information on
- * open firmware properties.
+ * See "Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml"
+ * for information on open firmware properties.
  *
  * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
  * sysfs interface.
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
index d8c9bfb202304..a0597db720864 100644
--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
@@ -1739,6 +1739,7 @@ static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
 			iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 			kvaser_pciefd_pwm_stop(can);
 			kvaser_pciefd_devlink_port_unregister(can);
+			timer_shutdown_sync(&can->bec_poll_timer);
 			free_candev(can->can.dev);
 		}
 	}
@@ -1879,7 +1880,7 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)
 		struct kvaser_pciefd_can *can = pcie->can[i];
 
 		unregister_candev(can->can.dev);
-		timer_delete(&can->bec_poll_timer);
+		timer_shutdown_sync(&can->bec_poll_timer);
 		kvaser_pciefd_pwm_stop(can);
 		kvaser_pciefd_devlink_port_unregister(can);
 	}
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index d11a7c88fc32f..d31179312026b 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -169,17 +169,17 @@ static void m_can_pci_remove(struct pci_dev *pci)
 	pci_free_irq_vectors(pci);
 }
 
-static __maybe_unused int m_can_pci_suspend(struct device *dev)
+static int m_can_pci_suspend(struct device *dev)
 {
 	return m_can_class_suspend(dev);
 }
 
-static __maybe_unused int m_can_pci_resume(struct device *dev)
+static int m_can_pci_resume(struct device *dev)
 {
 	return m_can_class_resume(dev);
 }
 
-static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
+static DEFINE_SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
 			 m_can_pci_suspend, m_can_pci_resume);
 
 static const struct pci_device_id m_can_pci_id_table[] = {
@@ -195,7 +195,7 @@ static struct pci_driver m_can_pci_driver = {
 	.remove = m_can_pci_remove,
 	.id_table = m_can_pci_id_table,
 	.driver = {
-		.pm = &m_can_pci_pm_ops,
+		.pm = pm_sleep_ptr(&m_can_pci_pm_ops),
 	},
 };
 
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index fcc37b73ed436..c643879673680 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -132,9 +132,9 @@
 #define RCANFD_CCTR_BEIE		BIT(8)
 #define RCANFD_CCTR_CSLPR		BIT(2)
 #define RCANFD_CCTR_CHMDC_MASK		(0x3)
-#define RCANFD_CCTR_CHDMC_COPM		(0x0)
-#define RCANFD_CCTR_CHDMC_CRESET	(0x1)
-#define RCANFD_CCTR_CHDMC_CHLT		(0x2)
+#define RCANFD_CCTR_CHMDC_COPM		(0x0)
+#define RCANFD_CCTR_CHMDC_CRESET	(0x1)
+#define RCANFD_CCTR_CHMDC_CHLT		(0x2)
 
 /* RSCFDnCFDCmSTS / RSCFDnCmSTS */
 #define RCANFD_CSTS_COMSTS		BIT(7)
@@ -436,7 +436,6 @@ struct rcar_canfd_hw_info {
 	u8 rnc_field_width;
 	u8 max_aflpn;
 	u8 max_cftml;
-	u8 max_channels;
 	u8 postdiv;
 	/* hardware features */
 	unsigned shared_global_irqs:1;	/* Has shared global irqs */
@@ -444,6 +443,8 @@ struct rcar_canfd_hw_info {
 	unsigned ch_interface_mode:1;	/* Has channel interface mode */
 	unsigned shared_can_regs:1;	/* Has shared classical can registers */
 	unsigned external_clk:1;	/* Has external clock */
+	unsigned fcan_pclk:1;		/* Has fcan sourced from pclk. */
+	unsigned fixed_canfd:1;		/* Has mode fixed to canfd. */
 };
 
 /* Channel priv data */
@@ -476,6 +477,7 @@ struct rcar_canfd_global {
 	struct reset_control *rstc1;
 	struct reset_control *rstc2;
 	const struct rcar_canfd_hw_info *info;
+	u8 max_channels;
 };
 
 /* CAN FD mode nominal rate constants */
@@ -611,12 +613,13 @@ static const struct rcar_canfd_hw_info rcar_gen3_hw_info = {
 	.rnc_field_width = 8,
 	.max_aflpn = 31,
 	.max_cftml = 15,
-	.max_channels = 2,
 	.postdiv = 2,
 	.shared_global_irqs = 1,
 	.ch_interface_mode = 0,
 	.shared_can_regs = 0,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {
@@ -628,12 +631,13 @@ static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {
 	.rnc_field_width = 16,
 	.max_aflpn = 127,
 	.max_cftml = 31,
-	.max_channels = 8,
 	.postdiv = 2,
 	.shared_global_irqs = 1,
 	.ch_interface_mode = 1,
 	.shared_can_regs = 1,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 static const struct rcar_canfd_hw_info rzg2l_hw_info = {
@@ -645,12 +649,32 @@ static const struct rcar_canfd_hw_info rzg2l_hw_info = {
 	.rnc_field_width = 8,
 	.max_aflpn = 31,
 	.max_cftml = 15,
-	.max_channels = 2,
 	.postdiv = 1,
 	.multi_channel_irqs = 1,
 	.ch_interface_mode = 0,
 	.shared_can_regs = 0,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
+};
+
+static const struct rcar_canfd_hw_info r9a08g045_hw_info = {
+	.nom_bittiming = &rcar_canfd_gen4_nom_bittiming_const,
+	.data_bittiming = &rcar_canfd_gen4_data_bittiming_const,
+	.tdc_const = &rcar_canfd_gen4_tdc_const,
+	.regs = &rcar_gen4_regs,
+	.sh = &rcar_gen4_shift_data,
+	.rnc_field_width = 16,
+	.max_aflpn = 15,
+	.max_cftml = 31,
+	.postdiv = 2,
+	.shared_global_irqs = 0,
+	.multi_channel_irqs = 1,
+	.ch_interface_mode = 1,
+	.shared_can_regs = 1,
+	.external_clk = 1,
+	.fcan_pclk = 1,
+	.fixed_canfd = 1,
 };
 
 static const struct rcar_canfd_hw_info r9a09g047_hw_info = {
@@ -662,12 +686,13 @@ static const struct rcar_canfd_hw_info r9a09g047_hw_info = {
 	.rnc_field_width = 16,
 	.max_aflpn = 63,
 	.max_cftml = 31,
-	.max_channels = 6,
 	.postdiv = 1,
 	.multi_channel_irqs = 1,
 	.ch_interface_mode = 1,
 	.shared_can_regs = 1,
 	.external_clk = 0,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 static const struct rcar_canfd_hw_info r9a09g077_hw_info = {
@@ -679,12 +704,13 @@ static const struct rcar_canfd_hw_info r9a09g077_hw_info = {
 	.rnc_field_width = 16,
 	.max_aflpn = 15,
 	.max_cftml = 31,
-	.max_channels = 2,
 	.postdiv = 1,
 	.multi_channel_irqs = 1,
 	.ch_interface_mode = 1,
 	.shared_can_regs = 1,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 /* Helper functions */
@@ -822,13 +848,13 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
 	}
 
 	/* Transition all Channels to reset mode */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_clear_bit(gpriv->base,
 				     RCANFD_CCTR(ch), RCANFD_CCTR_CSLPR);
 
 		rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch),
 				      RCANFD_CCTR_CHMDC_MASK,
-				      RCANFD_CCTR_CHDMC_CRESET);
+				      RCANFD_CCTR_CHMDC_CRESET);
 
 		/* Ensure Channel reset mode */
 		err = readl_poll_timeout((gpriv->base + RCANFD_CSTS(ch)), sts,
@@ -840,6 +866,9 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
 		}
 
 		/* Set the controller into appropriate mode */
+		if (gpriv->info->fixed_canfd)
+			continue;
+
 		if (gpriv->info->ch_interface_mode) {
 			/* Do not set CLOE and FDOE simultaneously */
 			if (!gpriv->fdmode) {
@@ -887,7 +916,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
 	rcar_canfd_set_bit(gpriv->base, RCANFD_GCFG, cfg);
 
 	/* Channel configuration settings */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_set_bit(gpriv->base, RCANFD_CCTR(ch),
 				   RCANFD_CCTR_ERRD);
 		rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch),
@@ -1258,7 +1287,7 @@ static irqreturn_t rcar_canfd_global_err_interrupt(int irq, void *dev_id)
 	struct rcar_canfd_global *gpriv = dev_id;
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels)
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
 		rcar_canfd_handle_global_err(gpriv, ch);
 
 	return IRQ_HANDLED;
@@ -1290,7 +1319,7 @@ static irqreturn_t rcar_canfd_global_receive_fifo_interrupt(int irq, void *dev_i
 	struct rcar_canfd_global *gpriv = dev_id;
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels)
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
 		rcar_canfd_handle_global_receive(gpriv, ch);
 
 	return IRQ_HANDLED;
@@ -1304,7 +1333,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
 	/* Global error interrupts still indicate a condition specific
 	 * to a channel. RxFIFO interrupt is a global interrupt.
 	 */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_handle_global_err(gpriv, ch);
 		rcar_canfd_handle_global_receive(gpriv, ch);
 	}
@@ -1400,7 +1429,7 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
 	u32 ch;
 
 	/* Common FIFO is a per channel resource */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_handle_channel_err(gpriv, ch);
 		rcar_canfd_handle_channel_tx(gpriv, ch);
 	}
@@ -1504,7 +1533,7 @@ static int rcar_canfd_start(struct net_device *ndev)
 
 	/* Set channel to Operational mode */
 	rcar_canfd_update_bit(priv->base, RCANFD_CCTR(ch),
-			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_COPM);
+			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHMDC_COPM);
 
 	/* Verify channel mode change */
 	err = readl_poll_timeout((priv->base + RCANFD_CSTS(ch)), sts,
@@ -1578,7 +1607,7 @@ static void rcar_canfd_stop(struct net_device *ndev)
 
 	/* Transition to channel reset mode  */
 	rcar_canfd_update_bit(priv->base, RCANFD_CCTR(ch),
-			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_CRESET);
+			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHMDC_CRESET);
 
 	/* Check Channel reset mode */
 	err = readl_poll_timeout((priv->base + RCANFD_CSTS(ch)), sts,
@@ -2037,7 +2066,7 @@ static int rcar_canfd_global_init(struct rcar_canfd_global *gpriv)
 	rcar_canfd_configure_controller(gpriv);
 
 	/* Configure per channel attributes */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		/* Configure Channel's Rx fifo */
 		rcar_canfd_configure_rx(gpriv, ch);
 
@@ -2110,14 +2139,18 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	bool fdmode = true;			/* CAN FD only mode - default */
 	char name[9] = "channelX";
 	u32 ch, fcan_freq;
+	u8 max_channels;
 	int i;
 
 	info = of_device_get_match_data(dev);
+	max_channels = of_get_child_count(dev->of_node);
+	if (max_channels > RCANFD_NUM_CHANNELS)
+		return -EINVAL;
 
 	if (of_property_read_bool(dev->of_node, "renesas,no-can-fd"))
 		fdmode = false;			/* Classical CAN only mode */
 
-	for (i = 0; i < info->max_channels; ++i) {
+	for (i = 0; i < max_channels; ++i) {
 		name[7] = '0' + i;
 		of_child = of_get_available_child_by_name(dev->of_node, name);
 		if (of_child) {
@@ -2164,6 +2197,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	gpriv->pdev = pdev;
 	gpriv->channels_mask = channels_mask;
 	gpriv->fdmode = fdmode;
+	gpriv->max_channels = max_channels;
 	gpriv->info = info;
 
 	if (of_property_read_bool(dev->of_node, "renesas,fd-only"))
@@ -2190,13 +2224,20 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	 */
 	gpriv->can_clk = devm_clk_get(dev, "can_clk");
 	if (IS_ERR(gpriv->can_clk) || (clk_get_rate(gpriv->can_clk) == 0)) {
-		gpriv->can_clk = devm_clk_get(dev, "canfd");
-		if (IS_ERR(gpriv->can_clk))
-			return dev_err_probe(dev, PTR_ERR(gpriv->can_clk),
-					     "cannot get canfd clock\n");
+		if (info->fcan_pclk) {
+			fcan_freq = clk_get_rate(gpriv->clkp);
+			gpriv->can_clk = NULL;
+		} else {
+			gpriv->can_clk = devm_clk_get(dev, "canfd");
+			if (IS_ERR(gpriv->can_clk))
+				return dev_err_probe(dev, PTR_ERR(gpriv->can_clk),
+						     "cannot get canfd clock\n");
+
+			fcan_freq = clk_get_rate(gpriv->can_clk);
+		}
 
 		/* CANFD clock may be further divided within the IP */
-		fcan_freq = clk_get_rate(gpriv->can_clk) / info->postdiv;
+		fcan_freq /= info->postdiv;
 	} else {
 		fcan_freq = clk_get_rate(gpriv->can_clk);
 		gpriv->extclk = gpriv->info->external_clk;
@@ -2258,7 +2299,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	if (err)
 		goto fail_mode;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		err = rcar_canfd_channel_probe(gpriv, ch, fcan_freq,
 					       transceivers[ch]);
 		if (err)
@@ -2272,7 +2313,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	return 0;
 
 fail_channel:
-	for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels)
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
 		rcar_canfd_channel_remove(gpriv, ch);
 fail_mode:
 	rcar_canfd_global_deinit(gpriv, false);
@@ -2285,7 +2326,7 @@ static void rcar_canfd_remove(struct platform_device *pdev)
 	struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev);
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_disable_channel_interrupts(gpriv->ch[ch]);
 		rcar_canfd_channel_remove(gpriv, ch);
 	}
@@ -2299,7 +2340,7 @@ static int rcar_canfd_suspend(struct device *dev)
 	int err;
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		struct rcar_canfd_channel *priv = gpriv->ch[ch];
 		struct net_device *ndev = priv->ndev;
 
@@ -2336,7 +2377,7 @@ static int rcar_canfd_resume(struct device *dev)
 		return err;
 	}
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		struct rcar_canfd_channel *priv = gpriv->ch[ch];
 		struct net_device *ndev = priv->ndev;
 
@@ -2361,6 +2402,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,
 
 static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {
 	{ .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info },
+	{ .compatible = "renesas,r9a08g045-canfd", .data = &r9a08g045_hw_info },
+	{ .compatible = "renesas,r9a08g046-canfd", .data = &r9a08g045_hw_info },
 	{ .compatible = "renesas,r9a09g047-canfd", .data = &r9a09g047_hw_info },
 	{ .compatible = "renesas,r9a09g077-canfd", .data = &r9a09g077_hw_info },
 	{ .compatible = "renesas,rcar-gen3-canfd", .data = &rcar_gen3_hw_info },
diff --git a/drivers/net/can/softing/Kconfig b/drivers/net/can/softing/Kconfig
deleted file mode 100644
index 8afd7d0a1000a..0000000000000
--- a/drivers/net/can/softing/Kconfig
+++ /dev/null
@@ -1,31 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config CAN_SOFTING
-	tristate "Softing Gmbh CAN generic support"
-	depends on HAS_IOMEM
-	help
-	  Support for CAN cards from Softing Gmbh & some cards
-	  from Vector Gmbh.
-	  Softing Gmbh CAN cards come with 1 or 2 physical buses.
-	  Those cards typically use Dual Port RAM to communicate
-	  with the host CPU. The interface is then identical for PCI
-	  and PCMCIA cards. This driver operates on a platform device,
-	  which has been created by softing_cs or softing_pci driver.
-	  Warning:
-	  The API of the card does not allow fine control per bus, but
-	  controls the 2 buses on the card together.
-	  As such, some actions (start/stop/busoff recovery) on 1 bus
-	  must bring down the other bus too temporarily.
-
-config CAN_SOFTING_CS
-	tristate "Softing Gmbh CAN pcmcia cards"
-	depends on PCMCIA
-	depends on CAN_SOFTING
-	help
-	  Support for PCMCIA cards from Softing Gmbh & some cards
-	  from Vector Gmbh.
-	  You need firmware for these, which you can get at
-	  https://github.com/linux-can/can-firmware
-	  This version of the driver is written against
-	  firmware version 4.6 (softing-fw-4.6-binaries.tar.gz)
-	  In order to use the card as CAN device, you need the Softing generic
-	  support too.
diff --git a/drivers/net/can/softing/Makefile b/drivers/net/can/softing/Makefile
deleted file mode 100644
index c511540003779..0000000000000
--- a/drivers/net/can/softing/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-softing-y := softing_main.o softing_fw.o
-obj-$(CONFIG_CAN_SOFTING) += softing.o
-obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o
diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h
deleted file mode 100644
index 2893007ea05e1..0000000000000
--- a/drivers/net/can/softing/softing.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * softing common interfaces
- *
- * by Kurt Van Dijck, 2008-2010
- */
-
-#include <linux/atomic.h>
-#include <linux/netdevice.h>
-#include <linux/ktime.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/can.h>
-#include <linux/can/dev.h>
-
-#include "softing_platform.h"
-
-struct softing;
-
-struct softing_priv {
-	struct can_priv can; /* must be the first member! */
-	struct net_device *netdev;
-	struct softing *card;
-	struct {
-		int pending;
-		/* variables which hold the circular buffer */
-		int echo_put;
-		int echo_get;
-	} tx;
-	struct can_bittiming_const btr_const;
-	int index;
-	uint8_t output;
-	uint16_t chip;
-};
-#define netdev2softing(netdev)	((struct softing_priv *)netdev_priv(netdev))
-
-struct softing {
-	const struct softing_platform_data *pdat;
-	struct platform_device *pdev;
-	struct net_device *net[2];
-	spinlock_t spin; /* protect this structure & DPRAM access */
-	ktime_t ts_ref;
-	ktime_t ts_overflow; /* timestamp overflow value, in ktime */
-
-	struct {
-		/* indication of firmware status */
-		int up;
-		/* protection of the 'up' variable */
-		struct mutex lock;
-	} fw;
-	struct {
-		int nr;
-		int requested;
-		int svc_count;
-		unsigned int dpram_position;
-	} irq;
-	struct {
-		int pending;
-		int last_bus;
-		/*
-		 * keep the bus that last tx'd a message,
-		 * in order to let every netdev queue resume
-		 */
-	} tx;
-	__iomem uint8_t *dpram;
-	unsigned long dpram_phys;
-	unsigned long dpram_size;
-	struct {
-		uint16_t fw_version, hw_version, license, serial;
-		uint16_t chip[2];
-		unsigned int freq; /* remote cpu's operating frequency */
-	} id;
-};
-
-int softing_default_output(struct net_device *netdev);
-
-ktime_t softing_raw2ktime(struct softing *card, u32 raw);
-
-int softing_chip_poweron(struct softing *card);
-
-int softing_bootloader_command(struct softing *card, int16_t cmd,
-			       const char *msg);
-
-/* Load firmware after reset */
-int softing_load_fw(const char *file, struct softing *card,
-		    __iomem uint8_t *virt, unsigned int size, int offset);
-
-/* Load final application firmware after bootloader */
-int softing_load_app_fw(const char *file, struct softing *card);
-
-/*
- * enable or disable irq
- * only called with fw.lock locked
- */
-int softing_enable_irq(struct softing *card, int enable);
-
-/* start/stop 1 bus on card */
-int softing_startstop(struct net_device *netdev, int up);
-
-/* netif_rx() */
-int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
-		      ktime_t ktime);
-
-/* SOFTING DPRAM mappings */
-#define DPRAM_RX		0x0000
-	#define DPRAM_RX_SIZE	32
-	#define DPRAM_RX_CNT	16
-#define DPRAM_RX_RD		0x0201	/* uint8_t */
-#define DPRAM_RX_WR		0x0205	/* uint8_t */
-#define DPRAM_RX_LOST		0x0207	/* uint8_t */
-
-#define DPRAM_FCT_PARAM		0x0300	/* int16_t [20] */
-#define DPRAM_FCT_RESULT	0x0328	/* int16_t */
-#define DPRAM_FCT_HOST		0x032b	/* uint16_t */
-
-#define DPRAM_INFO_BUSSTATE	0x0331	/* uint16_t */
-#define DPRAM_INFO_BUSSTATE2	0x0335	/* uint16_t */
-#define DPRAM_INFO_ERRSTATE	0x0339	/* uint16_t */
-#define DPRAM_INFO_ERRSTATE2	0x033d	/* uint16_t */
-#define DPRAM_RESET		0x0341	/* uint16_t */
-#define DPRAM_CLR_RECV_FIFO	0x0345	/* uint16_t */
-#define DPRAM_RESET_TIME	0x034d	/* uint16_t */
-#define DPRAM_TIME		0x0350	/* uint64_t */
-#define DPRAM_WR_START		0x0358	/* uint8_t */
-#define DPRAM_WR_END		0x0359	/* uint8_t */
-#define DPRAM_RESET_RX_FIFO	0x0361	/* uint16_t */
-#define DPRAM_RESET_TX_FIFO	0x0364	/* uint8_t */
-#define DPRAM_READ_FIFO_LEVEL	0x0365	/* uint8_t */
-#define DPRAM_RX_FIFO_LEVEL	0x0366	/* uint16_t */
-#define DPRAM_TX_FIFO_LEVEL	0x0366	/* uint16_t */
-
-#define DPRAM_TX		0x0400	/* uint16_t */
-	#define DPRAM_TX_SIZE	16
-	#define DPRAM_TX_CNT	32
-#define DPRAM_TX_RD		0x0601	/* uint8_t */
-#define DPRAM_TX_WR		0x0605	/* uint8_t */
-
-#define DPRAM_COMMAND		0x07e0	/* uint16_t */
-#define DPRAM_RECEIPT		0x07f0	/* uint16_t */
-#define DPRAM_IRQ_TOHOST	0x07fe	/* uint8_t */
-#define DPRAM_IRQ_TOCARD	0x07ff	/* uint8_t */
-
-#define DPRAM_V2_RESET		0x0e00	/* uint8_t */
-#define DPRAM_V2_IRQ_TOHOST	0x0e02	/* uint8_t */
-
-#define TXMAX	(DPRAM_TX_CNT - 1)
-
-/* DPRAM return codes */
-#define RES_NONE	0
-#define RES_OK		1
-#define RES_NOK		2
-#define RES_UNKNOWN	3
-/* DPRAM flags */
-#define CMD_TX		0x01
-#define CMD_ACK		0x02
-#define CMD_XTD		0x04
-#define CMD_RTR		0x08
-#define CMD_ERR		0x10
-#define CMD_BUS2	0x80
-
-/* returned fifo entry bus state masks */
-#define SF_MASK_BUSOFF		0x80
-#define SF_MASK_EPASSIVE	0x60
-
-/* bus states */
-#define STATE_BUSOFF	2
-#define STATE_EPASSIVE	1
-#define STATE_EACTIVE	0
diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c
deleted file mode 100644
index 3cea14cf055ad..0000000000000
--- a/drivers/net/can/softing/softing_cs.c
+++ /dev/null
@@ -1,335 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010
- *
- * - Kurt Van Dijck, EIA Electronics
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include "softing_platform.h"
-
-static int softingcs_index;
-static DEFINE_SPINLOCK(softingcs_index_lock);
-
-static int softingcs_reset(struct platform_device *pdev, int v);
-static int softingcs_enable_irq(struct platform_device *pdev, int v);
-
-/*
- * platform_data descriptions
- */
-#define MHZ (1000*1000)
-static const struct softing_platform_data softingcs_platform_data[] = {
-{
-	.name = "CANcard",
-	.manf = 0x0168, .prod = 0x001,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "CANcard-NEC",
-	.manf = 0x0168, .prod = 0x002,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "CANcard-SJA",
-	.manf = 0x0168, .prod = 0x004,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "CANcard-2",
-	.manf = 0x0168, .prod = 0x005,
-	.generation = 2,
-	.nbus = 2,
-	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x1000,
-	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = NULL,
-}, {
-	.name = "Vector-CANcard",
-	.manf = 0x0168, .prod = 0x081,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "Vector-CANcard-SJA",
-	.manf = 0x0168, .prod = 0x084,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "Vector-CANcard-2",
-	.manf = 0x0168, .prod = 0x085,
-	.generation = 2,
-	.nbus = 2,
-	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x1000,
-	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = NULL,
-}, {
-	.name = "EDICcard-NEC",
-	.manf = 0x0168, .prod = 0x102,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "EDICcard-2",
-	.manf = 0x0168, .prod = 0x105,
-	.generation = 2,
-	.nbus = 2,
-	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x1000,
-	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = NULL,
-}, {
-	0, 0,
-},
-};
-
-MODULE_FIRMWARE(fw_dir "bcard.bin");
-MODULE_FIRMWARE(fw_dir "ldcard.bin");
-MODULE_FIRMWARE(fw_dir "cancard.bin");
-MODULE_FIRMWARE(fw_dir "cansja.bin");
-
-MODULE_FIRMWARE(fw_dir "bcard2.bin");
-MODULE_FIRMWARE(fw_dir "ldcard2.bin");
-MODULE_FIRMWARE(fw_dir "cancrd2.bin");
-
-static const struct softing_platform_data
-*softingcs_find_platform_data(unsigned int manf, unsigned int prod)
-{
-	const struct softing_platform_data *lp;
-
-	for (lp = softingcs_platform_data; lp->manf; ++lp) {
-		if ((lp->manf == manf) && (lp->prod == prod))
-			return lp;
-	}
-	return NULL;
-}
-
-/*
- * platformdata callbacks
- */
-static int softingcs_reset(struct platform_device *pdev, int v)
-{
-	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
-
-	dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20);
-	return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);
-}
-
-static int softingcs_enable_irq(struct platform_device *pdev, int v)
-{
-	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
-
-	dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0);
-	return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);
-}
-
-/*
- * pcmcia check
- */
-static int softingcs_probe_config(struct pcmcia_device *pcmcia, void *priv_data)
-{
-	struct softing_platform_data *pdat = priv_data;
-	struct resource *pres;
-	int memspeed = 0;
-
-	WARN_ON(!pdat);
-	pres = pcmcia->resource[PCMCIA_IOMEM_0];
-	if (resource_size(pres) < 0x1000)
-		return -ERANGE;
-
-	pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	if (pdat->generation < 2) {
-		pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;
-		memspeed = 3;
-	} else {
-		pres->flags |= WIN_DATA_WIDTH_16;
-	}
-	return pcmcia_request_window(pcmcia, pres, memspeed);
-}
-
-static void softingcs_remove(struct pcmcia_device *pcmcia)
-{
-	struct platform_device *pdev = pcmcia->priv;
-
-	/* free bits */
-	platform_device_unregister(pdev);
-	/* release pcmcia stuff */
-	pcmcia_disable_device(pcmcia);
-}
-
-/*
- * platform_device wrapper
- * pdev->resource has 2 entries: io & irq
- */
-static void softingcs_pdev_release(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	kfree(pdev);
-}
-
-static int softingcs_probe(struct pcmcia_device *pcmcia)
-{
-	int ret;
-	struct platform_device *pdev;
-	const struct softing_platform_data *pdat;
-	struct resource *pres;
-	struct dev {
-		struct platform_device pdev;
-		struct resource res[2];
-	} *dev;
-
-	/* find matching platform_data */
-	pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id);
-	if (!pdat)
-		return -ENOTTY;
-
-	/* setup pcmcia device */
-	pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |
-		CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
-	ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);
-	if (ret)
-		goto pcmcia_failed;
-
-	ret = pcmcia_enable_device(pcmcia);
-	if (ret < 0)
-		goto pcmcia_failed;
-
-	pres = pcmcia->resource[PCMCIA_IOMEM_0];
-	if (!pres) {
-		ret = -EBADF;
-		goto pcmcia_bad;
-	}
-
-	/* create softing platform device */
-	dev = kzalloc_obj(*dev);
-	if (!dev) {
-		ret = -ENOMEM;
-		goto mem_failed;
-	}
-	dev->pdev.resource = dev->res;
-	dev->pdev.num_resources = ARRAY_SIZE(dev->res);
-	dev->pdev.dev.release = softingcs_pdev_release;
-
-	pdev = &dev->pdev;
-	pdev->dev.platform_data = (void *)pdat;
-	pdev->dev.parent = &pcmcia->dev;
-	pcmcia->priv = pdev;
-
-	/* platform device resources */
-	pdev->resource[0].flags = IORESOURCE_MEM;
-	pdev->resource[0].start = pres->start;
-	pdev->resource[0].end = pres->end;
-
-	pdev->resource[1].flags = IORESOURCE_IRQ;
-	pdev->resource[1].start = pcmcia->irq;
-	pdev->resource[1].end = pdev->resource[1].start;
-
-	/* platform device setup */
-	spin_lock(&softingcs_index_lock);
-	pdev->id = softingcs_index++;
-	spin_unlock(&softingcs_index_lock);
-	pdev->name = "softing";
-	dev_set_name(&pdev->dev, "softingcs.%i", pdev->id);
-	ret = platform_device_register(pdev);
-	if (ret < 0)
-		goto platform_failed;
-
-	dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev));
-	return 0;
-
-platform_failed:
-	platform_device_put(pdev);
-mem_failed:
-pcmcia_bad:
-pcmcia_failed:
-	pcmcia_disable_device(pcmcia);
-	pcmcia->priv = NULL;
-	return ret;
-}
-
-static const struct pcmcia_device_id softingcs_ids[] = {
-	/* softing */
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
-	/* vector, manufacturer? */
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
-	/* EDIC */
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
-	PCMCIA_DEVICE_NULL,
-};
-
-MODULE_DEVICE_TABLE(pcmcia, softingcs_ids);
-
-static struct pcmcia_driver softingcs_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "softingcs",
-	.id_table	= softingcs_ids,
-	.probe		= softingcs_probe,
-	.remove		= softingcs_remove,
-};
-
-module_pcmcia_driver(softingcs_driver);
-
-MODULE_DESCRIPTION("softing CANcard driver"
-		", links PCMCIA card to softing driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
deleted file mode 100644
index 282570daf3efe..0000000000000
--- a/drivers/net/can/softing/softing_fw.c
+++ /dev/null
@@ -1,700 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010
- *
- * - Kurt Van Dijck, EIA Electronics
- */
-
-#include <linux/firmware.h>
-#include <linux/sched/signal.h>
-#include <asm/div64.h>
-#include <asm/io.h>
-
-#include "softing.h"
-
-/*
- * low level DPRAM command.
- * Make sure that card->dpram[DPRAM_FCT_HOST] is preset
- */
-static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector,
-		const char *msg)
-{
-	int ret;
-	unsigned long stamp;
-
-	iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]);
-	iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]);
-	iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]);
-	/* be sure to flush this to the card */
-	wmb();
-	stamp = jiffies + 1 * HZ;
-	/* wait for card */
-	do {
-		/* DPRAM_FCT_HOST is _not_ aligned */
-		ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) +
-			(ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8);
-		/* don't have any cached variables */
-		rmb();
-		if (ret == RES_OK)
-			/* read return-value now */
-			return ioread16(&card->dpram[DPRAM_FCT_RESULT]);
-
-		if ((ret != vector) || time_after(jiffies, stamp))
-			break;
-		/* process context => relax */
-		usleep_range(500, 10000);
-	} while (1);
-
-	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
-	dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret);
-	return ret;
-}
-
-static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg)
-{
-	int ret;
-
-	ret = _softing_fct_cmd(card, cmd, 0, msg);
-	if (ret > 0) {
-		dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret);
-		ret = -EIO;
-	}
-	return ret;
-}
-
-int softing_bootloader_command(struct softing *card, int16_t cmd,
-		const char *msg)
-{
-	int ret;
-	unsigned long stamp;
-
-	iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]);
-	iowrite16(cmd, &card->dpram[DPRAM_COMMAND]);
-	/* be sure to flush this to the card */
-	wmb();
-	stamp = jiffies + 3 * HZ;
-	/* wait for card */
-	do {
-		ret = ioread16(&card->dpram[DPRAM_RECEIPT]);
-		/* don't have any cached variables */
-		rmb();
-		if (ret == RES_OK)
-			return 0;
-		if (time_after(jiffies, stamp))
-			break;
-		/* process context => relax */
-		usleep_range(500, 10000);
-	} while (!signal_pending(current));
-
-	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
-	dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret);
-	return ret;
-}
-
-static int fw_parse(const u8 **pmem, const u8 *limit, u16 *ptype,
-		    u32 *paddr, u16 *plen, const u8 **pdat)
-{
-	uint16_t checksum[2];
-	const u8 *mem;
-	const u8 *record_end;
-
-	/*
-	 * firmware records are a binary, unaligned stream composed of:
-	 * uint16_t type;
-	 * uint32_t addr;
-	 * uint16_t len;
-	 * uint8_t dat[len];
-	 * uint16_t checksum;
-	 * all values in little endian.
-	 * We could define a struct for this, with __attribute__((packed)),
-	 * but would that solve the alignment in _all_ cases (cfr. the
-	 * struct itself may be an odd address)?
-	 *
-	 * I chose to use leXX_to_cpup() since this solves both
-	 * endianness & alignment.
-	 */
-	mem = *pmem;
-	/* A record needs an 8-byte prefix and a 2-byte checksum. */
-	if (mem > limit || limit - mem < 10)
-		return -EINVAL;
-
-	*ptype = le16_to_cpup((void *)&mem[0]);
-	*paddr = le32_to_cpup((void *)&mem[2]);
-	*plen = le16_to_cpup((void *)&mem[6]);
-	if (*plen > limit - mem - 10)
-		return -EINVAL;
-
-	*pdat = &mem[8];
-	/* verify checksum */
-	record_end = &mem[8 + *plen];
-	checksum[0] = le16_to_cpup((void *)record_end);
-	for (checksum[1] = 0; mem < record_end; ++mem)
-		checksum[1] += *mem;
-	if (checksum[0] != checksum[1])
-		return -EINVAL;
-	/* increment */
-	*pmem += 10 + *plen;
-	return 0;
-}
-
-int softing_load_fw(const char *file, struct softing *card,
-		__iomem uint8_t *dpram, unsigned int size, int offset)
-{
-	const struct firmware *fw;
-	int ret;
-	const uint8_t *mem, *end, *dat;
-	uint16_t type, len;
-	uint32_t addr;
-	uint8_t *buf = NULL, *new_buf;
-	s64 dpram_offset;
-	int buflen = 0;
-	int8_t type_end = 0;
-
-	ret = request_firmware(&fw, file, &card->pdev->dev);
-	if (ret < 0)
-		return ret;
-	dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes"
-		", offset %c0x%04x\n",
-		card->pdat->name, file, (unsigned int)fw->size,
-		(offset >= 0) ? '+' : '-', (unsigned int)abs(offset));
-	/* parse the firmware */
-	mem = fw->data;
-	end = &mem[fw->size];
-	/* look for header record */
-	ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-	if (ret < 0)
-		goto failed;
-	if (type != 0xffff)
-		goto failed;
-	if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) {
-		ret = -EINVAL;
-		goto failed;
-	}
-	/* ok, we had a header */
-	while (mem < end) {
-		ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-		if (ret < 0)
-			goto failed;
-		if (type == 3) {
-			/* start address, not used here */
-			continue;
-		} else if (type == 1) {
-			/* eof */
-			type_end = 1;
-			break;
-		} else if (type != 0) {
-			ret = -EINVAL;
-			goto failed;
-		}
-
-		dpram_offset = (s64)addr + offset;
-		if (dpram_offset < 0 || dpram_offset > size ||
-		    len > size - dpram_offset) {
-			ret = -EINVAL;
-			goto failed;
-		}
-		memcpy_toio(&dpram[dpram_offset], dat, len);
-		/* be sure to flush caches from IO space */
-		mb();
-		if (len > buflen) {
-			/* align buflen */
-			buflen = (len + (1024-1)) & ~(1024-1);
-			new_buf = krealloc(buf, buflen, GFP_KERNEL);
-			if (!new_buf) {
-				ret = -ENOMEM;
-				goto failed;
-			}
-			buf = new_buf;
-		}
-		/* verify record data */
-		memcpy_fromio(buf, &dpram[dpram_offset], len);
-		if (memcmp(buf, dat, len)) {
-			/* is not ok */
-			dev_alert(&card->pdev->dev, "DPRAM readback failed\n");
-			ret = -EIO;
-			goto failed;
-		}
-	}
-	if (!type_end)
-		/* no end record seen */
-		goto failed;
-	ret = 0;
-failed:
-	kfree(buf);
-	release_firmware(fw);
-	if (ret < 0)
-		dev_info(&card->pdev->dev, "firmware %s failed\n", file);
-	return ret;
-}
-
-int softing_load_app_fw(const char *file, struct softing *card)
-{
-	const struct firmware *fw;
-	const uint8_t *mem, *end, *dat;
-	int ret, j;
-	uint16_t type, len;
-	uint32_t addr, start_addr = 0;
-	unsigned int sum, rx_sum;
-	int8_t type_end = 0, type_entrypoint = 0;
-
-	ret = request_firmware(&fw, file, &card->pdev->dev);
-	if (ret) {
-		dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n",
-			file, ret);
-		return ret;
-	}
-	dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n",
-		file, (unsigned long)fw->size);
-	/* parse the firmware */
-	mem = fw->data;
-	end = &mem[fw->size];
-	/* look for header record */
-	ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-	if (ret)
-		goto failed;
-	ret = -EINVAL;
-	if (type != 0xffff) {
-		dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n",
-			type);
-		goto failed;
-	}
-	if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) {
-		dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n",
-				len, dat);
-		goto failed;
-	}
-	/* ok, we had a header */
-	while (mem < end) {
-		ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-		if (ret)
-			goto failed;
-
-		if (type == 3) {
-			/* start address */
-			start_addr = addr;
-			type_entrypoint = 1;
-			continue;
-		} else if (type == 1) {
-			/* eof */
-			type_end = 1;
-			break;
-		} else if (type != 0) {
-			dev_alert(&card->pdev->dev,
-					"unknown record type 0x%04x\n", type);
-			ret = -EINVAL;
-			goto failed;
-		}
-
-		/* regular data */
-		for (sum = 0, j = 0; j < len; ++j)
-			sum += dat[j];
-		/* work in 16bit (target) */
-		sum &= 0xffff;
-
-		if (card->pdat->app.offs > card->dpram_size ||
-		    len > card->dpram_size - card->pdat->app.offs) {
-			ret = -EINVAL;
-			goto failed;
-		}
-
-		memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len);
-		iowrite32(card->pdat->app.offs + card->pdat->app.addr,
-				&card->dpram[DPRAM_COMMAND + 2]);
-		iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]);
-		iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]);
-		iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]);
-		ret = softing_bootloader_command(card, 1, "loading app.");
-		if (ret < 0)
-			goto failed;
-		/* verify checksum */
-		rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]);
-		if (rx_sum != sum) {
-			dev_alert(&card->pdev->dev, "SRAM seems to be damaged"
-				", wanted 0x%04x, got 0x%04x\n", sum, rx_sum);
-			ret = -EIO;
-			goto failed;
-		}
-	}
-	if (!type_end || !type_entrypoint)
-		goto failed;
-	/* start application in card */
-	iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]);
-	iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]);
-	ret = softing_bootloader_command(card, 3, "start app.");
-	if (ret < 0)
-		goto failed;
-	ret = 0;
-failed:
-	release_firmware(fw);
-	if (ret < 0)
-		dev_info(&card->pdev->dev, "firmware %s failed\n", file);
-	return ret;
-}
-
-static int softing_reset_chip(struct softing *card)
-{
-	int ret;
-
-	do {
-		/* reset chip */
-		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]);
-		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]);
-		iowrite8(1, &card->dpram[DPRAM_RESET]);
-		iowrite8(0, &card->dpram[DPRAM_RESET+1]);
-
-		ret = softing_fct_cmd(card, 0, "reset_can");
-		if (!ret)
-			break;
-		if (signal_pending(current))
-			/* don't wait any longer */
-			break;
-	} while (1);
-	card->tx.pending = 0;
-	return ret;
-}
-
-int softing_chip_poweron(struct softing *card)
-{
-	int ret;
-	/* sync */
-	ret = _softing_fct_cmd(card, 99, 0x55, "sync-a");
-	if (ret < 0)
-		goto failed;
-
-	ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b");
-	if (ret < 0)
-		goto failed;
-
-	ret = softing_reset_chip(card);
-	if (ret < 0)
-		goto failed;
-	/* get_serial */
-	ret = softing_fct_cmd(card, 43, "get_serial_number");
-	if (ret < 0)
-		goto failed;
-	card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]);
-	/* get_version */
-	ret = softing_fct_cmd(card, 12, "get_version");
-	if (ret < 0)
-		goto failed;
-	card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]);
-	card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]);
-	card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]);
-	card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]);
-	card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]);
-	return 0;
-failed:
-	return ret;
-}
-
-static void softing_initialize_timestamp(struct softing *card)
-{
-	uint64_t ovf;
-
-	card->ts_ref = ktime_get();
-
-	/* 16MHz is the reference */
-	ovf = 0x100000000ULL * 16;
-	do_div(ovf, card->pdat->freq ?: 16);
-
-	card->ts_overflow = ktime_add_us(0, ovf);
-}
-
-ktime_t softing_raw2ktime(struct softing *card, u32 raw)
-{
-	uint64_t rawl;
-	ktime_t now, real_offset;
-	ktime_t target;
-	ktime_t tmp;
-
-	now = ktime_get();
-	real_offset = ktime_sub(ktime_get_real(), now);
-
-	/* find nsec from card */
-	rawl = raw * 16;
-	do_div(rawl, card->pdat->freq ?: 16);
-	target = ktime_add_us(card->ts_ref, rawl);
-	/* test for overflows */
-	tmp = ktime_add(target, card->ts_overflow);
-	while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) {
-		card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow);
-		target = tmp;
-		tmp = ktime_add(target, card->ts_overflow);
-	}
-	return ktime_add(target, real_offset);
-}
-
-static inline int softing_error_reporting(struct net_device *netdev)
-{
-	struct softing_priv *priv = netdev_priv(netdev);
-
-	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
-		? 1 : 0;
-}
-
-int softing_startstop(struct net_device *dev, int up)
-{
-	int ret;
-	struct softing *card;
-	struct softing_priv *priv;
-	struct net_device *netdev;
-	int bus_bitmask_start;
-	int j, error_reporting;
-	struct can_frame msg;
-	const struct can_bittiming *bt;
-
-	priv = netdev_priv(dev);
-	card = priv->card;
-
-	if (!card->fw.up)
-		return -EIO;
-
-	ret = mutex_lock_interruptible(&card->fw.lock);
-	if (ret)
-		return ret;
-
-	bus_bitmask_start = 0;
-	if (up)
-		/* prepare to start this bus as well */
-		bus_bitmask_start |= (1 << priv->index);
-	/* bring netdevs down */
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		netdev = card->net[j];
-		if (!netdev)
-			continue;
-		priv = netdev_priv(netdev);
-
-		if (dev != netdev)
-			netif_stop_queue(netdev);
-
-		if (netif_running(netdev)) {
-			if (dev != netdev)
-				bus_bitmask_start |= (1 << j);
-			priv->tx.pending = 0;
-			priv->tx.echo_put = 0;
-			priv->tx.echo_get = 0;
-			/*
-			 * this bus' may just have called open_candev()
-			 * which is rather stupid to call close_candev()
-			 * already
-			 * but we may come here from busoff recovery too
-			 * in which case the echo_skb _needs_ flushing too.
-			 * just be sure to call open_candev() again
-			 */
-			close_candev(netdev);
-		}
-		priv->can.state = CAN_STATE_STOPPED;
-	}
-	card->tx.pending = 0;
-
-	softing_enable_irq(card, 0);
-	ret = softing_reset_chip(card);
-	if (ret)
-		goto failed;
-	if (!bus_bitmask_start)
-		/* no buses to be brought up */
-		goto card_done;
-
-	if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2)
-			&& (softing_error_reporting(card->net[0])
-				!= softing_error_reporting(card->net[1]))) {
-		dev_alert(&card->pdev->dev,
-				"err_reporting flag differs for buses\n");
-		goto invalid;
-	}
-	error_reporting = 0;
-	if (bus_bitmask_start & 1) {
-		netdev = card->net[0];
-		priv = netdev_priv(netdev);
-		error_reporting += softing_error_reporting(netdev);
-		/* init chip 1 */
-		bt = &priv->can.bittiming;
-		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		iowrite16(bt->phase_seg1 + bt->prop_seg,
-				&card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
-				&card->dpram[DPRAM_FCT_PARAM + 10]);
-		ret = softing_fct_cmd(card, 1, "initialize_chip[0]");
-		if (ret < 0)
-			goto failed;
-		/* set mode */
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		ret = softing_fct_cmd(card, 3, "set_mode[0]");
-		if (ret < 0)
-			goto failed;
-		/* set filter */
-		/* 11bit id & mask */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		/* 29bit id.lo & mask.lo & id.hi & mask.hi */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
-		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
-		ret = softing_fct_cmd(card, 7, "set_filter[0]");
-		if (ret < 0)
-			goto failed;
-		/* set output control */
-		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		ret = softing_fct_cmd(card, 5, "set_output[0]");
-		if (ret < 0)
-			goto failed;
-	}
-	if (bus_bitmask_start & 2) {
-		netdev = card->net[1];
-		priv = netdev_priv(netdev);
-		error_reporting += softing_error_reporting(netdev);
-		/* init chip2 */
-		bt = &priv->can.bittiming;
-		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		iowrite16(bt->phase_seg1 + bt->prop_seg,
-				&card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
-				&card->dpram[DPRAM_FCT_PARAM + 10]);
-		ret = softing_fct_cmd(card, 2, "initialize_chip[1]");
-		if (ret < 0)
-			goto failed;
-		/* set mode2 */
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		ret = softing_fct_cmd(card, 4, "set_mode[1]");
-		if (ret < 0)
-			goto failed;
-		/* set filter2 */
-		/* 11bit id & mask */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		/* 29bit id.lo & mask.lo & id.hi & mask.hi */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
-		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
-		ret = softing_fct_cmd(card, 8, "set_filter[1]");
-		if (ret < 0)
-			goto failed;
-		/* set output control2 */
-		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		ret = softing_fct_cmd(card, 6, "set_output[1]");
-		if (ret < 0)
-			goto failed;
-	}
-
-	/* enable_error_frame
-	 *
-	 * Error reporting is switched off at the moment since
-	 * the receiving of them is not yet 100% verified
-	 * This should be enabled sooner or later
-	 */
-	if (0 && error_reporting) {
-		ret = softing_fct_cmd(card, 51, "enable_error_frame");
-		if (ret < 0)
-			goto failed;
-	}
-
-	/* initialize interface */
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]);
-	ret = softing_fct_cmd(card, 17, "initialize_interface");
-	if (ret < 0)
-		goto failed;
-	/* enable_fifo */
-	ret = softing_fct_cmd(card, 36, "enable_fifo");
-	if (ret < 0)
-		goto failed;
-	/* enable fifo tx ack */
-	ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]");
-	if (ret < 0)
-		goto failed;
-	/* enable fifo tx ack2 */
-	ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]");
-	if (ret < 0)
-		goto failed;
-	/* start_chip */
-	ret = softing_fct_cmd(card, 11, "start_chip");
-	if (ret < 0)
-		goto failed;
-	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]);
-	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]);
-	if (card->pdat->generation < 2) {
-		iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
-		/* flush the DPRAM caches */
-		wmb();
-	}
-
-	softing_initialize_timestamp(card);
-
-	/*
-	 * do socketcan notifications/status changes
-	 * from here, no errors should occur, or the failed: part
-	 * must be reviewed
-	 */
-	memset(&msg, 0, sizeof(msg));
-	msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
-	msg.len = CAN_ERR_DLC;
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (!(bus_bitmask_start & (1 << j)))
-			continue;
-		netdev = card->net[j];
-		if (!netdev)
-			continue;
-		priv = netdev_priv(netdev);
-		priv->can.state = CAN_STATE_ERROR_ACTIVE;
-		open_candev(netdev);
-		if (dev != netdev) {
-			/* notify other buses on the restart */
-			softing_netdev_rx(netdev, &msg, 0);
-			++priv->can.can_stats.restarts;
-		}
-		netif_wake_queue(netdev);
-	}
-
-	/* enable interrupts */
-	ret = softing_enable_irq(card, 1);
-	if (ret)
-		goto failed;
-card_done:
-	mutex_unlock(&card->fw.lock);
-	return 0;
-invalid:
-	ret = -EINVAL;
-failed:
-	softing_enable_irq(card, 0);
-	softing_reset_chip(card);
-	mutex_unlock(&card->fw.lock);
-	/* bring all other interfaces down */
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		netdev = card->net[j];
-		if (!netdev)
-			continue;
-		dev_close(netdev);
-	}
-	return ret;
-}
-
-int softing_default_output(struct net_device *netdev)
-{
-	struct softing_priv *priv = netdev_priv(netdev);
-	struct softing *card = priv->card;
-
-	switch (priv->chip) {
-	case 1000:
-		return (card->pdat->generation < 2) ? 0xfb : 0xfa;
-	case 5:
-		return 0x60;
-	default:
-		return 0x40;
-	}
-}
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
deleted file mode 100644
index 519ab3097f866..0000000000000
--- a/drivers/net/can/softing/softing_main.c
+++ /dev/null
@@ -1,864 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010
- *
- * - Kurt Van Dijck, EIA Electronics
- */
-
-#include <linux/ethtool.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "softing.h"
-
-#define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1)
-
-/*
- * test is a specific CAN netdev
- * is online (ie. up 'n running, not sleeping, not busoff
- */
-static inline int canif_is_active(struct net_device *netdev)
-{
-	struct can_priv *can = netdev_priv(netdev);
-
-	if (!netif_running(netdev))
-		return 0;
-	return (can->state <= CAN_STATE_ERROR_PASSIVE);
-}
-
-/* reset DPRAM */
-static inline void softing_set_reset_dpram(struct softing *card)
-{
-	if (card->pdat->generation >= 2) {
-		spin_lock_bh(&card->spin);
-		iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) & ~1,
-				&card->dpram[DPRAM_V2_RESET]);
-		spin_unlock_bh(&card->spin);
-	}
-}
-
-static inline void softing_clr_reset_dpram(struct softing *card)
-{
-	if (card->pdat->generation >= 2) {
-		spin_lock_bh(&card->spin);
-		iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) | 1,
-				&card->dpram[DPRAM_V2_RESET]);
-		spin_unlock_bh(&card->spin);
-	}
-}
-
-/* trigger the tx queue-ing */
-static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
-		struct net_device *dev)
-{
-	struct softing_priv *priv = netdev_priv(dev);
-	struct softing *card = priv->card;
-	int ret;
-	uint8_t *ptr;
-	uint8_t fifo_wr, fifo_rd;
-	struct can_frame *cf = (struct can_frame *)skb->data;
-	uint8_t buf[DPRAM_TX_SIZE];
-
-	if (can_dev_dropped_skb(dev, skb))
-		return NETDEV_TX_OK;
-
-	spin_lock(&card->spin);
-
-	ret = NETDEV_TX_BUSY;
-	if (!card->fw.up ||
-			(card->tx.pending >= TXMAX) ||
-			(priv->tx.pending >= TX_ECHO_SKB_MAX))
-		goto xmit_done;
-	fifo_wr = ioread8(&card->dpram[DPRAM_TX_WR]);
-	fifo_rd = ioread8(&card->dpram[DPRAM_TX_RD]);
-	if (fifo_wr == fifo_rd)
-		/* fifo full */
-		goto xmit_done;
-	memset(buf, 0, sizeof(buf));
-	ptr = buf;
-	*ptr = CMD_TX;
-	if (cf->can_id & CAN_RTR_FLAG)
-		*ptr |= CMD_RTR;
-	if (cf->can_id & CAN_EFF_FLAG)
-		*ptr |= CMD_XTD;
-	if (priv->index)
-		*ptr |= CMD_BUS2;
-	++ptr;
-	*ptr++ = cf->len;
-	*ptr++ = (cf->can_id >> 0);
-	*ptr++ = (cf->can_id >> 8);
-	if (cf->can_id & CAN_EFF_FLAG) {
-		*ptr++ = (cf->can_id >> 16);
-		*ptr++ = (cf->can_id >> 24);
-	} else {
-		/* increment 1, not 2 as you might think */
-		ptr += 1;
-	}
-	if (!(cf->can_id & CAN_RTR_FLAG))
-		memcpy(ptr, &cf->data[0], cf->len);
-	memcpy_toio(&card->dpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr],
-			buf, DPRAM_TX_SIZE);
-	if (++fifo_wr >= DPRAM_TX_CNT)
-		fifo_wr = 0;
-	iowrite8(fifo_wr, &card->dpram[DPRAM_TX_WR]);
-	card->tx.last_bus = priv->index;
-	++card->tx.pending;
-	++priv->tx.pending;
-	can_put_echo_skb(skb, dev, priv->tx.echo_put, 0);
-	++priv->tx.echo_put;
-	if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
-		priv->tx.echo_put = 0;
-	/* can_put_echo_skb() saves the skb, safe to return TX_OK */
-	ret = NETDEV_TX_OK;
-xmit_done:
-	spin_unlock(&card->spin);
-	if (card->tx.pending >= TXMAX) {
-		int j;
-		for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-			if (card->net[j])
-				netif_stop_queue(card->net[j]);
-		}
-	}
-	if (ret != NETDEV_TX_OK)
-		netif_stop_queue(dev);
-
-	return ret;
-}
-
-/*
- * shortcut for skb delivery
- */
-int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
-		ktime_t ktime)
-{
-	struct sk_buff *skb;
-	struct can_frame *cf;
-
-	skb = alloc_can_skb(netdev, &cf);
-	if (!skb)
-		return -ENOMEM;
-	memcpy(cf, msg, sizeof(*msg));
-	skb->tstamp = ktime;
-	return netif_rx(skb);
-}
-
-/*
- * softing_handle_1
- * pop 1 entry from the DPRAM queue, and process
- */
-static int softing_handle_1(struct softing *card)
-{
-	struct net_device *netdev;
-	struct softing_priv *priv;
-	ktime_t ktime;
-	struct can_frame msg;
-	int cnt = 0, lost_msg;
-	uint8_t fifo_rd, fifo_wr, cmd;
-	uint8_t *ptr;
-	uint32_t tmp_u32;
-	uint8_t buf[DPRAM_RX_SIZE];
-
-	memset(&msg, 0, sizeof(msg));
-	/* test for lost msgs */
-	lost_msg = ioread8(&card->dpram[DPRAM_RX_LOST]);
-	if (lost_msg) {
-		int j;
-		/* reset condition */
-		iowrite8(0, &card->dpram[DPRAM_RX_LOST]);
-		/* prepare msg */
-		msg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
-		msg.len = CAN_ERR_DLC;
-		msg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
-		/*
-		 * service to all buses, we don't know which it was applicable
-		 * but only service buses that are online
-		 */
-		for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-			netdev = card->net[j];
-			if (!netdev)
-				continue;
-			if (!canif_is_active(netdev))
-				/* a dead bus has no overflows */
-				continue;
-			++netdev->stats.rx_over_errors;
-			softing_netdev_rx(netdev, &msg, 0);
-		}
-		/* prepare for other use */
-		memset(&msg, 0, sizeof(msg));
-		++cnt;
-	}
-
-	fifo_rd = ioread8(&card->dpram[DPRAM_RX_RD]);
-	fifo_wr = ioread8(&card->dpram[DPRAM_RX_WR]);
-
-	if (++fifo_rd >= DPRAM_RX_CNT)
-		fifo_rd = 0;
-	if (fifo_wr == fifo_rd)
-		return cnt;
-
-	memcpy_fromio(buf, &card->dpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd],
-			DPRAM_RX_SIZE);
-	mb();
-	/* trigger dual port RAM */
-	iowrite8(fifo_rd, &card->dpram[DPRAM_RX_RD]);
-
-	ptr = buf;
-	cmd = *ptr++;
-	if (cmd == 0xff)
-		/* not quite useful, probably the card has got out */
-		return 0;
-	netdev = card->net[0];
-	if (cmd & CMD_BUS2)
-		netdev = card->net[1];
-	priv = netdev_priv(netdev);
-
-	if (cmd & CMD_ERR) {
-		uint8_t can_state, state;
-
-		state = *ptr++;
-
-		msg.can_id = CAN_ERR_FLAG;
-		msg.len = CAN_ERR_DLC;
-
-		if (state & SF_MASK_BUSOFF) {
-			can_state = CAN_STATE_BUS_OFF;
-			msg.can_id |= CAN_ERR_BUSOFF;
-			state = STATE_BUSOFF;
-		} else if (state & SF_MASK_EPASSIVE) {
-			can_state = CAN_STATE_ERROR_PASSIVE;
-			msg.can_id |= CAN_ERR_CRTL;
-			msg.data[1] = CAN_ERR_CRTL_TX_PASSIVE;
-			state = STATE_EPASSIVE;
-		} else {
-			can_state = CAN_STATE_ERROR_ACTIVE;
-			msg.can_id |= CAN_ERR_CRTL;
-			state = STATE_EACTIVE;
-		}
-		/* update DPRAM */
-		iowrite8(state, &card->dpram[priv->index ?
-				DPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]);
-		/* timestamp */
-		tmp_u32 = le32_to_cpup((void *)ptr);
-		ktime = softing_raw2ktime(card, tmp_u32);
-
-		++netdev->stats.rx_errors;
-		/* update internal status */
-		if (can_state != priv->can.state) {
-			priv->can.state = can_state;
-			if (can_state == CAN_STATE_ERROR_PASSIVE)
-				++priv->can.can_stats.error_passive;
-			else if (can_state == CAN_STATE_BUS_OFF) {
-				/* this calls can_close_cleanup() */
-				++priv->can.can_stats.bus_off;
-				can_bus_off(netdev);
-				netif_stop_queue(netdev);
-			}
-			/* trigger socketcan */
-			softing_netdev_rx(netdev, &msg, ktime);
-		}
-
-	} else {
-		if (cmd & CMD_RTR)
-			msg.can_id |= CAN_RTR_FLAG;
-		msg.len = can_cc_dlc2len(*ptr++);
-		if (cmd & CMD_XTD) {
-			msg.can_id |= CAN_EFF_FLAG;
-			msg.can_id |= le32_to_cpup((void *)ptr);
-			ptr += 4;
-		} else {
-			msg.can_id |= le16_to_cpup((void *)ptr);
-			ptr += 2;
-		}
-		/* timestamp */
-		tmp_u32 = le32_to_cpup((void *)ptr);
-		ptr += 4;
-		ktime = softing_raw2ktime(card, tmp_u32);
-		if (!(msg.can_id & CAN_RTR_FLAG))
-			memcpy(&msg.data[0], ptr, 8);
-		/* update socket */
-		if (cmd & CMD_ACK) {
-			/* acknowledge, was tx msg */
-			struct sk_buff *skb;
-			skb = priv->can.echo_skb[priv->tx.echo_get];
-			if (skb)
-				skb->tstamp = ktime;
-			++netdev->stats.tx_packets;
-			netdev->stats.tx_bytes +=
-				can_get_echo_skb(netdev, priv->tx.echo_get,
-						 NULL);
-			++priv->tx.echo_get;
-			if (priv->tx.echo_get >= TX_ECHO_SKB_MAX)
-				priv->tx.echo_get = 0;
-			if (priv->tx.pending)
-				--priv->tx.pending;
-			if (card->tx.pending)
-				--card->tx.pending;
-		} else {
-			int ret;
-
-			ret = softing_netdev_rx(netdev, &msg, ktime);
-			if (ret == NET_RX_SUCCESS) {
-				++netdev->stats.rx_packets;
-				if (!(msg.can_id & CAN_RTR_FLAG))
-					netdev->stats.rx_bytes += msg.len;
-			} else {
-				++netdev->stats.rx_dropped;
-			}
-		}
-	}
-	++cnt;
-	return cnt;
-}
-
-/*
- * real interrupt handler
- */
-static irqreturn_t softing_irq_thread(int irq, void *dev_id)
-{
-	struct softing *card = (struct softing *)dev_id;
-	struct net_device *netdev;
-	struct softing_priv *priv;
-	int j, offset, work_done;
-
-	work_done = 0;
-	spin_lock_bh(&card->spin);
-	while (softing_handle_1(card) > 0) {
-		++card->irq.svc_count;
-		++work_done;
-	}
-	spin_unlock_bh(&card->spin);
-	/* resume tx queue's */
-	offset = card->tx.last_bus;
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (card->tx.pending >= TXMAX)
-			break;
-		netdev = card->net[(j + offset + 1) % card->pdat->nbus];
-		if (!netdev)
-			continue;
-		priv = netdev_priv(netdev);
-		if (!canif_is_active(netdev))
-			/* it makes no sense to wake dead buses */
-			continue;
-		if (priv->tx.pending >= TX_ECHO_SKB_MAX)
-			continue;
-		++work_done;
-		netif_wake_queue(netdev);
-	}
-	return work_done ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/*
- * interrupt routines:
- * schedule the 'real interrupt handler'
- */
-static irqreturn_t softing_irq_v2(int irq, void *dev_id)
-{
-	struct softing *card = (struct softing *)dev_id;
-	uint8_t ir;
-
-	ir = ioread8(&card->dpram[DPRAM_V2_IRQ_TOHOST]);
-	iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
-	return (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE;
-}
-
-static irqreturn_t softing_irq_v1(int irq, void *dev_id)
-{
-	struct softing *card = (struct softing *)dev_id;
-	uint8_t ir;
-
-	ir = ioread8(&card->dpram[DPRAM_IRQ_TOHOST]);
-	iowrite8(0, &card->dpram[DPRAM_IRQ_TOHOST]);
-	return ir ? IRQ_WAKE_THREAD : IRQ_NONE;
-}
-
-/*
- * netdev/candev interoperability
- */
-static int softing_netdev_open(struct net_device *ndev)
-{
-	int ret;
-
-	/* check or determine and set bittime */
-	ret = open_candev(ndev);
-	if (ret)
-		return ret;
-
-	ret = softing_startstop(ndev, 1);
-	if (ret < 0)
-		close_candev(ndev);
-
-	return ret;
-}
-
-static int softing_netdev_stop(struct net_device *ndev)
-{
-	netif_stop_queue(ndev);
-
-	/* softing cycle does close_candev() */
-	return softing_startstop(ndev, 0);
-}
-
-static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode)
-{
-	int ret;
-
-	switch (mode) {
-	case CAN_MODE_START:
-		/* softing_startstop does close_candev() */
-		ret = softing_startstop(ndev, 1);
-		return ret;
-	case CAN_MODE_STOP:
-	case CAN_MODE_SLEEP:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-/*
- * Softing device management helpers
- */
-int softing_enable_irq(struct softing *card, int enable)
-{
-	int ret;
-
-	if (!card->irq.nr) {
-		return 0;
-	} else if (card->irq.requested && !enable) {
-		free_irq(card->irq.nr, card);
-		card->irq.requested = 0;
-	} else if (!card->irq.requested && enable) {
-		ret = request_threaded_irq(card->irq.nr,
-				(card->pdat->generation >= 2) ?
-					softing_irq_v2 : softing_irq_v1,
-				softing_irq_thread, IRQF_SHARED,
-				dev_name(&card->pdev->dev), card);
-		if (ret) {
-			dev_alert(&card->pdev->dev,
-					"request_threaded_irq(%u) failed\n",
-					card->irq.nr);
-			return ret;
-		}
-		card->irq.requested = 1;
-	}
-	return 0;
-}
-
-static void softing_card_shutdown(struct softing *card)
-{
-	int fw_up = 0;
-
-	if (mutex_lock_interruptible(&card->fw.lock)) {
-		/* return -ERESTARTSYS */;
-	}
-	fw_up = card->fw.up;
-	card->fw.up = 0;
-
-	if (card->irq.requested && card->irq.nr) {
-		free_irq(card->irq.nr, card);
-		card->irq.requested = 0;
-	}
-	if (fw_up) {
-		if (card->pdat->enable_irq)
-			card->pdat->enable_irq(card->pdev, 0);
-		softing_set_reset_dpram(card);
-		if (card->pdat->reset)
-			card->pdat->reset(card->pdev, 1);
-	}
-	mutex_unlock(&card->fw.lock);
-}
-
-static int softing_card_boot(struct softing *card)
-{
-	int ret, j;
-	static const uint8_t stream[] = {
-		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, };
-	unsigned char back[sizeof(stream)];
-
-	if (mutex_lock_interruptible(&card->fw.lock))
-		return -ERESTARTSYS;
-	if (card->fw.up) {
-		mutex_unlock(&card->fw.lock);
-		return 0;
-	}
-	/* reset board */
-	if (card->pdat->enable_irq)
-		card->pdat->enable_irq(card->pdev, 1);
-	/* boot card */
-	softing_set_reset_dpram(card);
-	if (card->pdat->reset)
-		card->pdat->reset(card->pdev, 1);
-	for (j = 0; (j + sizeof(stream)) < card->dpram_size;
-			j += sizeof(stream)) {
-
-		memcpy_toio(&card->dpram[j], stream, sizeof(stream));
-		/* flush IO cache */
-		mb();
-		memcpy_fromio(back, &card->dpram[j], sizeof(stream));
-
-		if (!memcmp(back, stream, sizeof(stream)))
-			continue;
-		/* memory is not equal */
-		dev_alert(&card->pdev->dev, "dpram failed at 0x%04x\n", j);
-		ret = -EIO;
-		goto failed;
-	}
-	wmb();
-	/* load boot firmware */
-	ret = softing_load_fw(card->pdat->boot.fw, card, card->dpram,
-				card->dpram_size,
-				card->pdat->boot.offs - card->pdat->boot.addr);
-	if (ret < 0)
-		goto failed;
-	/* load loader firmware */
-	ret = softing_load_fw(card->pdat->load.fw, card, card->dpram,
-				card->dpram_size,
-				card->pdat->load.offs - card->pdat->load.addr);
-	if (ret < 0)
-		goto failed;
-
-	if (card->pdat->reset)
-		card->pdat->reset(card->pdev, 0);
-	softing_clr_reset_dpram(card);
-	ret = softing_bootloader_command(card, 0, "card boot");
-	if (ret < 0)
-		goto failed;
-	ret = softing_load_app_fw(card->pdat->app.fw, card);
-	if (ret < 0)
-		goto failed;
-
-	ret = softing_chip_poweron(card);
-	if (ret < 0)
-		goto failed;
-
-	card->fw.up = 1;
-	mutex_unlock(&card->fw.lock);
-	return 0;
-failed:
-	card->fw.up = 0;
-	if (card->pdat->enable_irq)
-		card->pdat->enable_irq(card->pdev, 0);
-	softing_set_reset_dpram(card);
-	if (card->pdat->reset)
-		card->pdat->reset(card->pdev, 1);
-	mutex_unlock(&card->fw.lock);
-	return ret;
-}
-
-/*
- * netdev sysfs
- */
-static ssize_t show_chip(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct net_device *ndev = to_net_dev(dev);
-	struct softing_priv *priv = netdev2softing(ndev);
-
-	return sprintf(buf, "%i\n", priv->chip);
-}
-
-static ssize_t show_output(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct net_device *ndev = to_net_dev(dev);
-	struct softing_priv *priv = netdev2softing(ndev);
-
-	return sprintf(buf, "0x%02x\n", priv->output);
-}
-
-static ssize_t store_output(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct net_device *ndev = to_net_dev(dev);
-	struct softing_priv *priv = netdev2softing(ndev);
-	struct softing *card = priv->card;
-	unsigned long val;
-	int ret;
-
-	ret = kstrtoul(buf, 0, &val);
-	if (ret < 0)
-		return ret;
-	val &= 0xFF;
-
-	ret = mutex_lock_interruptible(&card->fw.lock);
-	if (ret)
-		return -ERESTARTSYS;
-	if (netif_running(ndev)) {
-		mutex_unlock(&card->fw.lock);
-		return -EBUSY;
-	}
-	priv->output = val;
-	mutex_unlock(&card->fw.lock);
-	return count;
-}
-
-static const DEVICE_ATTR(chip, 0444, show_chip, NULL);
-static const DEVICE_ATTR(output, 0644, show_output, store_output);
-
-static const struct attribute *const netdev_sysfs_attrs[] = {
-	&dev_attr_chip.attr,
-	&dev_attr_output.attr,
-	NULL,
-};
-static const struct attribute_group netdev_sysfs_group = {
-	.name = NULL,
-	.attrs = (struct attribute **)netdev_sysfs_attrs,
-};
-
-static const struct net_device_ops softing_netdev_ops = {
-	.ndo_open = softing_netdev_open,
-	.ndo_stop = softing_netdev_stop,
-	.ndo_start_xmit	= softing_netdev_start_xmit,
-};
-
-static const struct ethtool_ops softing_ethtool_ops = {
-	.get_ts_info = ethtool_op_get_ts_info,
-};
-
-static const struct can_bittiming_const softing_btr_const = {
-	.name = KBUILD_MODNAME,
-	.tseg1_min = 1,
-	.tseg1_max = 16,
-	.tseg2_min = 1,
-	.tseg2_max = 8,
-	.sjw_max = 4, /* overruled */
-	.brp_min = 1,
-	.brp_max = 32, /* overruled */
-	.brp_inc = 1,
-};
-
-
-static struct net_device *softing_netdev_create(struct softing *card,
-						uint16_t chip_id)
-{
-	struct net_device *netdev;
-	struct softing_priv *priv;
-
-	netdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
-	if (!netdev) {
-		dev_alert(&card->pdev->dev, "alloc_candev failed\n");
-		return NULL;
-	}
-	priv = netdev_priv(netdev);
-	priv->netdev = netdev;
-	priv->card = card;
-	memcpy(&priv->btr_const, &softing_btr_const, sizeof(priv->btr_const));
-	priv->btr_const.brp_max = card->pdat->max_brp;
-	priv->btr_const.sjw_max = card->pdat->max_sjw;
-	priv->can.bittiming_const = &priv->btr_const;
-	priv->can.clock.freq = 8000000;
-	priv->chip = chip_id;
-	priv->output = softing_default_output(netdev);
-	SET_NETDEV_DEV(netdev, &card->pdev->dev);
-
-	netdev->flags |= IFF_ECHO;
-	netdev->netdev_ops = &softing_netdev_ops;
-	netdev->ethtool_ops = &softing_ethtool_ops;
-	priv->can.do_set_mode = softing_candev_set_mode;
-	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
-
-	return netdev;
-}
-
-static int softing_netdev_register(struct net_device *netdev)
-{
-	int ret;
-
-	ret = register_candev(netdev);
-	if (ret) {
-		dev_alert(&netdev->dev, "register failed\n");
-		return ret;
-	}
-	if (sysfs_create_group(&netdev->dev.kobj, &netdev_sysfs_group) < 0)
-		netdev_alert(netdev, "sysfs group failed\n");
-
-	return 0;
-}
-
-static void softing_netdev_cleanup(struct net_device *netdev)
-{
-	sysfs_remove_group(&netdev->dev.kobj, &netdev_sysfs_group);
-	unregister_candev(netdev);
-	free_candev(netdev);
-}
-
-/*
- * sysfs for Platform device
- */
-#define DEV_ATTR_RO(name, member) \
-static ssize_t show_##name(struct device *dev, \
-		struct device_attribute *attr, char *buf) \
-{ \
-	struct softing *card = dev_get_drvdata(dev); \
-	return sprintf(buf, "%u\n", card->member); \
-} \
-static DEVICE_ATTR(name, 0444, show_##name, NULL)
-
-#define DEV_ATTR_RO_STR(name, member) \
-static ssize_t show_##name(struct device *dev, \
-		struct device_attribute *attr, char *buf) \
-{ \
-	struct softing *card = dev_get_drvdata(dev); \
-	return sprintf(buf, "%s\n", card->member); \
-} \
-static DEVICE_ATTR(name, 0444, show_##name, NULL)
-
-DEV_ATTR_RO(serial, id.serial);
-DEV_ATTR_RO_STR(firmware, pdat->app.fw);
-DEV_ATTR_RO(firmware_version, id.fw_version);
-DEV_ATTR_RO_STR(hardware, pdat->name);
-DEV_ATTR_RO(hardware_version, id.hw_version);
-DEV_ATTR_RO(license, id.license);
-
-static struct attribute *softing_pdev_attrs[] = {
-	&dev_attr_serial.attr,
-	&dev_attr_firmware.attr,
-	&dev_attr_firmware_version.attr,
-	&dev_attr_hardware.attr,
-	&dev_attr_hardware_version.attr,
-	&dev_attr_license.attr,
-	NULL,
-};
-
-static const struct attribute_group softing_pdev_group = {
-	.name = NULL,
-	.attrs = softing_pdev_attrs,
-};
-
-/*
- * platform driver
- */
-static void softing_pdev_remove(struct platform_device *pdev)
-{
-	struct softing *card = platform_get_drvdata(pdev);
-	int j;
-
-	/* first, disable card*/
-	softing_card_shutdown(card);
-
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (!card->net[j])
-			continue;
-		softing_netdev_cleanup(card->net[j]);
-		card->net[j] = NULL;
-	}
-	sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
-
-	iounmap(card->dpram);
-	kfree(card);
-}
-
-static int softing_pdev_probe(struct platform_device *pdev)
-{
-	const struct softing_platform_data *pdat = dev_get_platdata(&pdev->dev);
-	struct softing *card;
-	struct net_device *netdev;
-	struct softing_priv *priv;
-	struct resource *pres;
-	int ret;
-	int j;
-
-	if (!pdat) {
-		dev_warn(&pdev->dev, "no platform data\n");
-		return -EINVAL;
-	}
-	if (pdat->nbus > ARRAY_SIZE(card->net)) {
-		dev_warn(&pdev->dev, "%u nets??\n", pdat->nbus);
-		return -EINVAL;
-	}
-
-	card = kzalloc_obj(*card);
-	if (!card)
-		return -ENOMEM;
-	card->pdat = pdat;
-	card->pdev = pdev;
-	platform_set_drvdata(pdev, card);
-	mutex_init(&card->fw.lock);
-	spin_lock_init(&card->spin);
-
-	ret = -EINVAL;
-	pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!pres)
-		goto platform_resource_failed;
-	card->dpram_phys = pres->start;
-	card->dpram_size = resource_size(pres);
-	card->dpram = ioremap(card->dpram_phys, card->dpram_size);
-	if (!card->dpram) {
-		dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
-		goto ioremap_failed;
-	}
-
-	pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (pres)
-		card->irq.nr = pres->start;
-
-	/* reset card */
-	ret = softing_card_boot(card);
-	if (ret < 0) {
-		dev_alert(&pdev->dev, "failed to boot\n");
-		goto boot_failed;
-	}
-
-	/* only now, the chip's are known */
-	card->id.freq = card->pdat->freq;
-
-	ret = sysfs_create_group(&pdev->dev.kobj, &softing_pdev_group);
-	if (ret < 0) {
-		dev_alert(&card->pdev->dev, "sysfs failed\n");
-		goto sysfs_failed;
-	}
-
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		card->net[j] = netdev =
-			softing_netdev_create(card, card->id.chip[j]);
-		if (!netdev) {
-			dev_alert(&pdev->dev, "failed to make can[%i]", j);
-			ret = -ENOMEM;
-			goto netdev_failed;
-		}
-		netdev->dev_id = j;
-		priv = netdev_priv(card->net[j]);
-		priv->index = j;
-		ret = softing_netdev_register(netdev);
-		if (ret) {
-			free_candev(netdev);
-			card->net[j] = NULL;
-			dev_alert(&card->pdev->dev,
-					"failed to register can[%i]\n", j);
-			goto netdev_failed;
-		}
-	}
-	dev_info(&card->pdev->dev, "%s ready.\n", card->pdat->name);
-	return 0;
-
-netdev_failed:
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (!card->net[j])
-			continue;
-		softing_netdev_cleanup(card->net[j]);
-	}
-	sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
-sysfs_failed:
-	softing_card_shutdown(card);
-boot_failed:
-	iounmap(card->dpram);
-ioremap_failed:
-platform_resource_failed:
-	kfree(card);
-	return ret;
-}
-
-static struct platform_driver softing_driver = {
-	.driver = {
-		.name = KBUILD_MODNAME,
-	},
-	.probe = softing_pdev_probe,
-	.remove = softing_pdev_remove,
-};
-
-module_platform_driver(softing_driver);
-
-MODULE_ALIAS("platform:softing");
-MODULE_DESCRIPTION("Softing DPRAM CAN driver");
-MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h
deleted file mode 100644
index cd8d7904c5f08..0000000000000
--- a/drivers/net/can/softing/softing_platform.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/platform_device.h>
-
-#ifndef _SOFTING_DEVICE_H_
-#define _SOFTING_DEVICE_H_
-
-/* softing firmware directory prefix */
-#define fw_dir "softing-4.6/"
-
-struct softing_platform_data {
-	unsigned int manf;
-	unsigned int prod;
-	/*
-	 * generation
-	 * 1st with NEC or SJA1000
-	 * 8bit, exclusive interrupt, ...
-	 * 2nd only SJA1000
-	 * 16bit, shared interrupt
-	 */
-	int generation;
-	int nbus; /* # buses on device */
-	unsigned int freq; /* operating frequency in Hz */
-	unsigned int max_brp;
-	unsigned int max_sjw;
-	unsigned long dpram_size;
-	const char *name;
-	struct {
-		unsigned long offs;
-		unsigned long addr;
-		const char *fw;
-	} boot, load, app;
-	/*
-	 * reset() function
-	 * bring pdev in or out of reset, depending on value
-	 */
-	int (*reset)(struct platform_device *pdev, int value);
-	int (*enable_irq)(struct platform_device *pdev, int value);
-};
-
-#endif
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index ae90e6716de5b..076a3efa1bfff 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -972,7 +972,7 @@ static void hi3110_can_remove(struct spi_device *spi)
 	free_candev(net);
 }
 
-static int __maybe_unused hi3110_can_suspend(struct device *dev)
+static int hi3110_can_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct hi3110_priv *priv = spi_get_drvdata(spi);
@@ -1002,7 +1002,7 @@ static int __maybe_unused hi3110_can_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused hi3110_can_resume(struct device *dev)
+static int hi3110_can_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct hi3110_priv *priv = spi_get_drvdata(spi);
@@ -1022,13 +1022,13 @@ static int __maybe_unused hi3110_can_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend, hi3110_can_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend, hi3110_can_resume);
 
 static struct spi_driver hi3110_can_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
 		.of_match_table = hi3110_of_match,
-		.pm = &hi3110_can_pm_ops,
+		.pm = pm_sleep_ptr(&hi3110_can_pm_ops),
 	},
 	.id_table = hi3110_id_table,
 	.probe = hi3110_can_probe,
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 0d0190ae094a1..d971890487b6c 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1490,7 +1490,7 @@ static void mcp251x_can_remove(struct spi_device *spi)
 	free_candev(net);
 }
 
-static int __maybe_unused mcp251x_can_suspend(struct device *dev)
+static int mcp251x_can_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_priv *priv = spi_get_drvdata(spi);
@@ -1517,7 +1517,7 @@ static int __maybe_unused mcp251x_can_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused mcp251x_can_resume(struct device *dev)
+static int mcp251x_can_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_priv *priv = spi_get_drvdata(spi);
@@ -1551,14 +1551,14 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
+static DEFINE_SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
 	mcp251x_can_resume);
 
 static struct spi_driver mcp251x_can_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
 		.of_match_table = mcp251x_of_match,
-		.pm = &mcp251x_can_pm_ops,
+		.pm = pm_sleep_ptr(&mcp251x_can_pm_ops),
 	},
 	.id_table = mcp251x_id_table,
 	.probe = mcp251x_can_probe,
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index f441f2265299e..8759bc05bd8f0 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -2213,6 +2213,7 @@ MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table);
 
 static int mcp251xfd_probe(struct spi_device *spi)
 {
+	const struct mcp251xfd_devtype_data *devtype_data;
 	struct net_device *ndev;
 	struct mcp251xfd_priv *priv;
 	struct gpio_desc *rx_int;
@@ -2222,6 +2223,10 @@ static int mcp251xfd_probe(struct spi_device *spi)
 	u32 freq = 0;
 	int err;
 
+	devtype_data = spi_get_device_match_data(spi);
+	if (!devtype_data)
+		return -ENODATA;
+
 	if (!spi->irq)
 		return dev_err_probe(&spi->dev, -ENXIO,
 				     "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n");
@@ -2307,7 +2312,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
 	priv->reg_vdd = reg_vdd;
 	priv->reg_xceiver = reg_xceiver;
 	priv->xstbyen = device_property_present(&spi->dev, "microchip,xstbyen");
-	priv->devtype_data = *(struct mcp251xfd_devtype_data *)spi_get_device_match_data(spi);
+	priv->devtype_data = *devtype_data;
 
 	/* Errata Reference:
 	 * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789E 4.,
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index af52285d5a4e0..76db6d09d1e6b 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -812,9 +812,12 @@ MODULE_DEVICE_TABLE(of, sun4ican_of_match);
 static void sun4ican_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+	struct sun4ican_priv *priv = netdev_priv(dev);
+	struct clk *clk = priv->clk;
 
 	unregister_netdev(dev);
 	free_candev(dev);
+	clk_put(clk);
 }
 
 static int sun4ican_probe(struct platform_device *pdev)
@@ -854,13 +857,13 @@ static int sun4ican_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		err = -ENODEV;
-		goto exit;
+		goto exit_put_clk;
 	}
 
 	addr = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(addr)) {
 		err = PTR_ERR(addr);
-		goto exit;
+		goto exit_put_clk;
 	}
 
 	dev = alloc_candev(sizeof(struct sun4ican_priv), 1);
@@ -868,7 +871,7 @@ static int sun4ican_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev,
 			"could not allocate memory for CAN device\n");
 		err = -ENOMEM;
-		goto exit;
+		goto exit_put_clk;
 	}
 
 	dev->netdev_ops = &sun4ican_netdev_ops;
@@ -908,6 +911,8 @@ static int sun4ican_probe(struct platform_device *pdev)
 
 exit_free:
 	free_candev(dev);
+exit_put_clk:
+	clk_put(clk);
 exit:
 	return err;
 }
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 24cf8f651f8f1..2d31f0b86859c 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -748,7 +748,7 @@ static void unlink_all_urbs(struct ems_usb *dev)
 {
 	int i;
 
-	usb_unlink_urb(dev->intr_urb);
+	usb_kill_urb(dev->intr_urb);
 
 	usb_kill_anchored_urbs(&dev->rx_submitted);
 
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
index 46a1b6907a500..2e862120ec3ff 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
@@ -161,7 +161,6 @@ struct kvaser_usb_net_priv {
  * @dev_get_data_busparams:	readback data busparams
  * @dev_get_berr_counter:	used for can.do_get_berr_counter
  *
- * @dev_setup_endpoints:	setup USB in and out endpoints
  * @dev_init_card:		initialize card
  * @dev_init_channel:		initialize channel
  * @dev_remove_channel:		uninitialize channel
@@ -189,7 +188,6 @@ struct kvaser_usb_dev_ops {
 	int (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv);
 	int (*dev_get_berr_counter)(const struct net_device *netdev,
 				    struct can_berr_counter *bec);
-	int (*dev_setup_endpoints)(struct kvaser_usb *dev);
 	int (*dev_init_card)(struct kvaser_usb *dev);
 	int (*dev_init_channel)(struct kvaser_usb_net_priv *priv);
 	void (*dev_remove_channel)(struct kvaser_usb_net_priv *priv);
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index d0a2a2a33c1c8..9687dfb89b4cc 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -926,6 +926,23 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
 	return err;
 }
 
+static int kvaser_usb_setup_endpoints(struct kvaser_usb *dev)
+{
+	struct usb_host_interface *iface_desc;
+	int ret;
+
+	iface_desc = dev->intf->cur_altsetting;
+
+	/* use first bulk endpoint for in and out */
+	ret = usb_find_common_endpoints(iface_desc, &dev->bulk_in,
+					&dev->bulk_out, NULL, NULL);
+
+	if (ret)
+		return -ENODEV;
+
+	return 0;
+}
+
 static int kvaser_usb_probe(struct usb_interface *intf,
 			    const struct usb_device_id *id)
 {
@@ -949,7 +966,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,
 	dev->driver_info = driver_info;
 	ops = driver_info->ops;
 
-	err = ops->dev_setup_endpoints(dev);
+	err = kvaser_usb_setup_endpoints(dev);
 	if (err) {
 		dev_err_probe(&intf->dev, err, "Cannot get usb endpoint(s)");
 		goto free_devlink;
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index efbb7bed34c9d..2220d197abb55 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -37,9 +37,6 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_kcan;
 static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc;
 static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt;
 
-#define KVASER_USB_HYDRA_BULK_EP_IN_ADDR	0x82
-#define KVASER_USB_HYDRA_BULK_EP_OUT_ADDR	0x02
-
 #define KVASER_USB_HYDRA_MAX_TRANSID		0xff
 #define KVASER_USB_HYDRA_MIN_TRANSID		0x01
 
@@ -536,6 +533,82 @@ static size_t kvaser_usb_hydra_cmd_size(struct kvaser_cmd *cmd)
 	return ret;
 }
 
+/* -EAGAIN means incomplete; -EINVAL rejects an invalid command length. */
+static int kvaser_usb_hydra_cmd_size_rx(struct kvaser_cmd *cmd,
+					size_t remaining, size_t *cmd_len)
+{
+	if (remaining < sizeof(cmd->header.cmd_no))
+		return -EAGAIN;
+
+	if (cmd->header.cmd_no == CMD_EXTENDED &&
+	    remaining < offsetof(struct kvaser_cmd_ext, cmd_no_ext))
+		return -EAGAIN;
+
+	*cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+	if (cmd->header.cmd_no != CMD_EXTENDED)
+		return 0;
+
+	if (*cmd_len < offsetof(struct kvaser_cmd_ext, rx_can) ||
+	    *cmd_len > KVASER_USB_HYDRA_MAX_CMD_LEN)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int kvaser_usb_hydra_verify_cmd_size(const struct kvaser_cmd *cmd,
+					    size_t cmd_len)
+{
+	const struct kvaser_cmd_ext *cmd_ext;
+	size_t min_len;
+
+	if (cmd->header.cmd_no != CMD_EXTENDED)
+		return 0;
+
+	cmd_ext = (const struct kvaser_cmd_ext *)cmd;
+
+	/* Keep this switch in sync with kvaser_usb_hydra_handle_cmd_ext(). */
+	switch (cmd_ext->cmd_no_ext) {
+	case CMD_TX_ACKNOWLEDGE_FD:
+		min_len = offsetof(struct kvaser_cmd_ext, tx_ack.timestamp) +
+			  sizeof(cmd_ext->tx_ack.timestamp);
+		break;
+
+	case CMD_RX_MESSAGE_FD: {
+		u32 flags;
+
+		min_len = offsetof(struct kvaser_cmd_ext, rx_can.kcan_payload);
+		if (cmd_len < min_len)
+			return -EINVAL;
+
+		flags = le32_to_cpu(cmd_ext->rx_can.flags);
+		if (flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {
+			min_len += sizeof(cmd_ext->rx_can.err_frame_data);
+		} else if (!(flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME)) {
+			u32 kcan_header;
+			u8 dlc;
+
+			kcan_header = le32_to_cpu(cmd_ext->rx_can.kcan_header);
+			dlc = (kcan_header & KVASER_USB_KCAN_DATA_DLC_MASK) >>
+				KVASER_USB_KCAN_DATA_DLC_SHIFT;
+
+			if (flags & KVASER_USB_HYDRA_CF_FLAG_FDF)
+				min_len += can_fd_dlc2len(dlc);
+			else
+				min_len += can_cc_dlc2len(dlc);
+		}
+		break;
+	}
+
+	default:
+		return 0;
+	}
+
+	if (cmd_len < min_len)
+		return -EINVAL;
+
+	return 0;
+}
+
 static struct kvaser_usb_net_priv *
 kvaser_usb_hydra_net_priv_from_cmd(const struct kvaser_usb *dev,
 				   const struct kvaser_cmd *cmd)
@@ -675,8 +748,9 @@ static int kvaser_usb_hydra_wait_cmd(const struct kvaser_usb *dev, u8 cmd_no,
 			size_t cmd_len;
 
 			tmp_cmd = buf + pos;
-			cmd_len = kvaser_usb_hydra_cmd_size(tmp_cmd);
-			if (pos + cmd_len > actual_len) {
+			err = kvaser_usb_hydra_cmd_size_rx(tmp_cmd, actual_len - pos, &cmd_len);
+			if (err || pos + cmd_len > actual_len ||
+			    kvaser_usb_hydra_verify_cmd_size(tmp_cmd, cmd_len)) {
 				dev_err_ratelimited(&dev->intf->dev,
 						    "Format error\n");
 				break;
@@ -1733,32 +1807,6 @@ static int kvaser_usb_hydra_get_berr_counter(const struct net_device *netdev,
 	return 0;
 }
 
-static int kvaser_usb_hydra_setup_endpoints(struct kvaser_usb *dev)
-{
-	const struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *ep;
-	int i;
-
-	iface_desc = dev->intf->cur_altsetting;
-
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		ep = &iface_desc->endpoint[i].desc;
-
-		if (!dev->bulk_in && usb_endpoint_is_bulk_in(ep) &&
-		    ep->bEndpointAddress == KVASER_USB_HYDRA_BULK_EP_IN_ADDR)
-			dev->bulk_in = ep;
-
-		if (!dev->bulk_out && usb_endpoint_is_bulk_out(ep) &&
-		    ep->bEndpointAddress == KVASER_USB_HYDRA_BULK_EP_OUT_ADDR)
-			dev->bulk_out = ep;
-
-		if (dev->bulk_in && dev->bulk_out)
-			return 0;
-	}
-
-	return -ENODEV;
-}
-
 static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev)
 {
 	int err;
@@ -2120,27 +2168,61 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,
 	spin_lock_irqsave(usb_rx_leftover_lock, irq_flags);
 	usb_rx_leftover_len = card_data->usb_rx_leftover_len;
 	if (usb_rx_leftover_len) {
+		const size_t cmd_size_field_end = offsetof(struct kvaser_cmd_ext, cmd_no_ext);
 		int remaining_bytes;
+		int err;
 
 		cmd = (struct kvaser_cmd *)card_data->usb_rx_leftover;
 
-		cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+		if (cmd->header.cmd_no == CMD_EXTENDED &&
+		    usb_rx_leftover_len < cmd_size_field_end) {
+			remaining_bytes = min_t(int, len, cmd_size_field_end - usb_rx_leftover_len);
+
+			memcpy(card_data->usb_rx_leftover + usb_rx_leftover_len, buf,
+			       remaining_bytes);
+			usb_rx_leftover_len += remaining_bytes;
+			card_data->usb_rx_leftover_len = usb_rx_leftover_len;
+			pos += remaining_bytes;
+
+			if (usb_rx_leftover_len < cmd_size_field_end) {
+				spin_unlock_irqrestore(usb_rx_leftover_lock,
+						       irq_flags);
+				return;
+			}
+		}
 
-		remaining_bytes = min_t(unsigned int, len,
+		err = kvaser_usb_hydra_cmd_size_rx(cmd, usb_rx_leftover_len,
+						   &cmd_len);
+		if (err || cmd_len < usb_rx_leftover_len) {
+			dev_err(&dev->intf->dev, "Format error\n");
+			card_data->usb_rx_leftover_len = 0;
+			spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
+			return;
+		}
+
+		remaining_bytes = min_t(unsigned int, len - pos,
 					cmd_len - usb_rx_leftover_len);
 		/* Make sure we do not overflow usb_rx_leftover */
 		if (remaining_bytes + usb_rx_leftover_len >
 						KVASER_USB_HYDRA_MAX_CMD_LEN) {
 			dev_err(&dev->intf->dev, "Format error\n");
+			card_data->usb_rx_leftover_len = 0;
 			spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
 			return;
 		}
 
-		memcpy(card_data->usb_rx_leftover + usb_rx_leftover_len, buf,
+		memcpy(card_data->usb_rx_leftover + usb_rx_leftover_len, buf + pos,
 		       remaining_bytes);
 		pos += remaining_bytes;
 
 		if (remaining_bytes + usb_rx_leftover_len == cmd_len) {
+			if (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {
+				dev_err(&dev->intf->dev, "Format error\n");
+				card_data->usb_rx_leftover_len = 0;
+				spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
+				return;
+			}
+
 			kvaser_usb_hydra_handle_cmd(dev, cmd);
 			usb_rx_leftover_len = 0;
 		} else {
@@ -2152,11 +2234,17 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,
 	spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
 
 	while (pos < len) {
+		int err;
+
 		cmd = buf + pos;
 
-		cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+		err = kvaser_usb_hydra_cmd_size_rx(cmd, len - pos, &cmd_len);
+		if (err && err != -EAGAIN) {
+			dev_err(&dev->intf->dev, "Format error\n");
+			return;
+		}
 
-		if (pos + cmd_len > len) {
+		if (err == -EAGAIN || pos + cmd_len > len) {
 			/* We got first part of a command */
 			int leftover_bytes;
 
@@ -2174,6 +2262,11 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,
 			break;
 		}
 
+		if (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {
+			dev_err(&dev->intf->dev, "Format error\n");
+			return;
+		}
+
 		kvaser_usb_hydra_handle_cmd(dev, cmd);
 		pos += cmd_len;
 	}
@@ -2203,7 +2296,6 @@ const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = {
 	.dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming,
 	.dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams,
 	.dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter,
-	.dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints,
 	.dev_init_card = kvaser_usb_hydra_init_card,
 	.dev_init_channel = kvaser_usb_hydra_init_channel,
 	.dev_get_software_info = kvaser_usb_hydra_get_software_info,
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index a876c7819b81c..00302b5c6223e 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -1964,22 +1964,6 @@ static int kvaser_usb_leaf_get_berr_counter(const struct net_device *netdev,
 	return 0;
 }
 
-static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
-{
-	struct usb_host_interface *iface_desc;
-	int ret;
-
-	iface_desc = dev->intf->cur_altsetting;
-
-	/* use first bulk endpoint for in and out */
-	ret = usb_find_common_endpoints(iface_desc, &dev->bulk_in, &dev->bulk_out,
-					NULL, NULL);
-	if (ret)
-		return -ENODEV;
-
-	return 0;
-}
-
 const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
 	.dev_set_mode = kvaser_usb_leaf_set_mode,
 	.dev_set_bittiming = kvaser_usb_leaf_set_bittiming,
@@ -1987,7 +1971,6 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
 	.dev_set_data_bittiming = NULL,
 	.dev_get_data_busparams = NULL,
 	.dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter,
-	.dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints,
 	.dev_init_card = kvaser_usb_leaf_init_card,
 	.dev_init_channel = kvaser_usb_leaf_init_channel,
 	.dev_remove_channel = kvaser_usb_leaf_remove_channel,
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index f72e0644c5fdb..6b088a05a901e 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -61,7 +61,7 @@
  *    the following way:
  *
  *	m[n].len <=> the length if message n(including the header in bytes)
- *	m[n] is is aligned to a 4 byte boundary, hence
+ *	m[n] is aligned to a 4 byte boundary, hence
  *	  offset(m[0])	 := 0;
  *	  offset(m[n+1]) := offset(m[n]) + (m[n].len + 3) & 3
  *
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 43d7f22820b88..52661e0882054 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -157,6 +157,7 @@ enum xcan_reg {
 #define XCAN_2_FSR_RI_MASK		0x0000003F /* RX Read Index */
 #define XCAN_DLCR_EDL_MASK		0x08000000 /* EDL Mask in DLC */
 #define XCAN_DLCR_BRS_MASK		0x04000000 /* BRS Mask in DLC */
+#define XCAN_DLCR_ESI_MASK		0x02000000 /* ESI Mask in DLC */
 #define XCAN_ECC_CFG_REECRX_MASK	BIT(2) /* Reset RX FIFO ECC error counters */
 #define XCAN_ECC_CFG_REECTXOL_MASK	BIT(1) /* Reset TXOL FIFO ECC error counters */
 #define XCAN_ECC_CFG_REECTXTL_MASK	BIT(0) /* Reset TXTL FIFO ECC error counters */
@@ -959,6 +960,11 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base)
 
 	/* Check the frame received is FD or not*/
 	if (dlc & XCAN_DLCR_EDL_MASK) {
+		if (dlc & XCAN_DLCR_BRS_MASK)
+			cf->flags |= CANFD_BRS;
+		if (dlc & XCAN_DLCR_ESI_MASK)
+			cf->flags |= CANFD_ESI;
+
 		for (i = 0; i < cf->len; i += 4) {
 			dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) +
 					(dwindex * XCANFD_DW_BYTES);
diff --git a/include/linux/can/core.h b/include/linux/can/core.h
index 2de74c2b78b6c..effb5c31ef401 100644
--- a/include/linux/can/core.h
+++ b/include/linux/can/core.h
@@ -51,7 +51,7 @@ extern void can_proto_unregister(const struct can_proto *cp);
 int can_rx_register(struct net *net, struct net_device *dev,
 		    canid_t can_id, canid_t mask,
 		    void (*func)(struct sk_buff *, void *),
-		    void *data, char *ident, struct sock *sk);
+		    void *data, u64 ino, struct sock *sk);
 
 extern void can_rx_unregister(struct net *net, struct net_device *dev,
 			      canid_t can_id, canid_t mask,
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 6d0710d6f571d..346faddee02eb 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -176,7 +176,7 @@ static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *s
 	return can_dropped_invalid_skb(dev, skb);
 
 invalid_skb:
-	kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 	dev->stats.tx_dropped++;
 	return true;
 }
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 5d27843862fca..87ace09c0d8bd 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -78,12 +78,12 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
 
 	nskb = skb_clone(skb, GFP_ATOMIC);
 	if (unlikely(!nskb)) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return NULL;
 	}
 
 	can_skb_set_owner(nskb, skb->sk);
-	consume_skb(skb);
+	dev_consume_skb_any(skb);
 	return nskb;
 }
 
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 34fe3b28d576f..d97f85fc3232d 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -226,7 +226,7 @@ int can_send(struct sk_buff *skb, int loop)
 		goto inval_skb;
 	}
 
-	if (unlikely(skb->dev->type != ARPHRD_CAN)) {
+	if (unlikely(!can_get_ml_priv(skb->dev))) {
 		err = -EPERM;
 		goto inval_skb;
 	}
@@ -418,7 +418,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  * @mask: CAN mask (see description)
  * @func: callback function on filter match
  * @data: returned parameter for callback function
- * @ident: string for calling module identification
+ * @ino: inode number of sock (0 = unknown)
  * @sk: socket pointer (might be NULL)
  *
  * Description:
@@ -443,7 +443,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  */
 int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 		    canid_t mask, void (*func)(struct sk_buff *, void *),
-		    void *data, char *ident, struct sock *sk)
+		    void *data, u64 ino, struct sock *sk)
 {
 	struct receiver *rcv;
 	struct hlist_head *rcv_list;
@@ -452,7 +452,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 
 	/* insert new receiver  (dev,canid,mask) -> (func,data) */
 
-	if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev)))
+	if (dev && !can_get_ml_priv(dev))
 		return -ENODEV;
 
 	if (dev && !net_eq(net, dev_net(dev)))
@@ -472,7 +472,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 	atomic_long_set(&rcv->matches, 0);
 	rcv->func = func;
 	rcv->data = data;
-	rcv->ident = ident;
+	rcv->ino = ino;
 	rcv->sk = sk;
 
 	hlist_add_head_rcu(&rcv->list, rcv_list);
@@ -519,7 +519,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
 	struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats;
 	struct can_dev_rcv_lists *dev_rcv_lists;
 
-	if (dev && dev->type != ARPHRD_CAN)
+	if (dev && !can_get_ml_priv(dev))
 		return;
 
 	if (dev && !net_eq(net, dev_net(dev)))
@@ -684,8 +684,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct can_skb_ext *csx = can_skb_ext_find(skb);
 
-	if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
-		     !csx || !can_is_can_skb(skb))) {
+	if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_can_skb(skb))) {
 		pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
 			     dev->type, skb->len);
 
@@ -710,8 +709,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct can_skb_ext *csx = can_skb_ext_find(skb);
 
-	if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
-		     !csx || !can_is_canfd_skb(skb))) {
+	if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canfd_skb(skb))) {
 		pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
 			     dev->type, skb->len);
 
@@ -736,8 +734,7 @@ static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct can_skb_ext *csx = can_skb_ext_find(skb);
 
-	if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
-		     !csx || !can_is_canxl_skb(skb))) {
+	if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canxl_skb(skb))) {
 		pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
 			     dev->type, skb->len);
 
diff --git a/net/can/af_can.h b/net/can/af_can.h
index 87887014f5628..6e593ed5db5f0 100644
--- a/net/can/af_can.h
+++ b/net/can/af_can.h
@@ -55,7 +55,7 @@ struct receiver {
 	atomic_long_t matches;
 	void (*func)(struct sk_buff *skb, void *data);
 	void *data;
-	char *ident;
+	u64 ino;
 	struct sock *sk;
 	struct rcu_head rcu;
 };
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 3d637a1e0ac1a..301920011a300 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -54,6 +54,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/can.h>
+#include <linux/can/can-ml.h>
 #include <linux/can/core.h>
 #include <linux/can/skb.h>
 #include <linux/can/bcm.h>
@@ -220,9 +221,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 	struct bcm_sock *bo = bcm_sk(sk);
 	struct bcm_op *op;
 
-	seq_printf(m, ">>> socket %pK", sk->sk_socket);
-	seq_printf(m, " / sk %pK", sk);
-	seq_printf(m, " / bo %pK", bo);
+	seq_printf(m, ">>> sock inode %s", bo->procname);
 	seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
 	seq_printf(m, " / bound %s", bcm_proc_getifname(net, ifname, bo->ifindex));
 	seq_printf(m, " <<<\n");
@@ -1536,7 +1535,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 						      op->can_id,
 						      REGMASK(op->can_id),
 						      bcm_rx_handler, op,
-						      "bcm", sk);
+						      sock_i_ino(sk), sk);
 
 				/* keep a tracked reference so that a later
 				 * unregister can safely reach the device even
@@ -1560,7 +1559,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 		} else {
 			err = can_rx_register(sock_net(sk), NULL, op->can_id,
 					      REGMASK(op->can_id),
-					      bcm_rx_handler, op, "bcm", sk);
+					      bcm_rx_handler, op,
+					      sock_i_ino(sk), sk);
 		}
 
 		if (err) {
@@ -1719,7 +1719,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 				goto out_release;
 			}
 
-			if (dev->type != ARPHRD_CAN) {
+			if (!can_get_ml_priv(dev)) {
 				dev_put(dev);
 				ret = -ENODEV;
 				goto out_release;
@@ -1867,7 +1867,7 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
 		return NOTIFY_DONE;
@@ -1926,21 +1926,19 @@ static int bcm_release(struct socket *sock)
 
 	/* remove bcm_ops, timer, rx_unregister(), etc. */
 
-	spin_lock(&bcm_notifier_lock);
-	while (bcm_busy_notifier == bo) {
-		spin_unlock(&bcm_notifier_lock);
-		schedule_timeout_uninterruptible(1);
-		spin_lock(&bcm_notifier_lock);
-	}
-	list_del(&bo->notifier);
-	spin_unlock(&bcm_notifier_lock);
-
+	/* Remove the procfs entry and the tx_ops before taking RTNL:
+	 * remove_proc_entry() waits for concurrent readers of the entry and
+	 * must not hold up RTNL for them. Clear bo->bcm_proc_read so that
+	 * bcm_notify() does not remove the entry a second time.
+	 */
 	lock_sock(sk);
 
 #if IS_ENABLED(CONFIG_PROC_FS)
 	/* remove procfs entry */
-	if (net->can.bcmproc_dir && bo->bcm_proc_read)
+	if (net->can.bcmproc_dir && bo->bcm_proc_read) {
 		remove_proc_entry(bo->procname, net->can.bcmproc_dir);
+		bo->bcm_proc_read = NULL;
+	}
 #endif /* CONFIG_PROC_FS */
 
 	list_for_each_entry_safe(op, next, &bo->tx_ops, list) {
@@ -1948,6 +1946,21 @@ static int bcm_release(struct socket *sock)
 		bcm_remove_op(op);
 	}
 
+	release_sock(sk);
+
+	rtnl_lock();
+
+	/* The netdev notifier chain runs under RTNL, so bcm_notifier() can't
+	 * be walking bcm_notifier_list and point to this socket. The spinlock
+	 * is still needed as bcm_init() adds sockets without holding RTNL.
+	 */
+	spin_lock(&bcm_notifier_lock);
+	WARN_ON_ONCE(bcm_busy_notifier == bo);
+	list_del(&bo->notifier);
+	spin_unlock(&bcm_notifier_lock);
+
+	lock_sock(sk);
+
 	list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
 		/*
 		 * Don't care if we're bound or not (due to netdev problems)
@@ -1973,6 +1986,8 @@ static int bcm_release(struct socket *sock)
 
 	}
 
+	rtnl_unlock();
+
 	synchronize_rcu();
 
 	list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
@@ -2024,7 +2039,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
 			ret = -ENODEV;
 			goto fail;
 		}
-		if (dev->type != ARPHRD_CAN) {
+		if (!can_get_ml_priv(dev)) {
 			dev_put(dev);
 			ret = -ENODEV;
 			goto fail;
@@ -2040,8 +2055,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
 
 #if IS_ENABLED(CONFIG_PROC_FS)
 	if (net->can.bcmproc_dir) {
-		/* unique socket address as filename */
-		sprintf(bo->procname, "%llu", sock_i_ino(sk));
+		/* use unique socket inode number as filename */
+		snprintf(bo->procname, sizeof(bo->procname),
+			 "%llu", sock_i_ino(sk));
 		bo->bcm_proc_read = proc_create_net_single(bo->procname, 0644,
 						     net->can.bcmproc_dir,
 						     bcm_proc_show, sk);
diff --git a/net/can/gw.c b/net/can/gw.c
index 5793cb2420ed3..8a5327d8a00e8 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -52,6 +52,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/can.h>
+#include <linux/can/can-ml.h>
 #include <linux/can/core.h>
 #include <linux/can/skb.h>
 #include <linux/can/gw.h>
@@ -579,7 +580,7 @@ static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
 {
 	return can_rx_register(net, gwj->src.dev, gwj->ccgw.filter.can_id,
 			       gwj->ccgw.filter.can_mask, can_can_gw_rcv,
-			       gwj, "gw", NULL);
+			       gwj, 0, NULL);
 }
 
 static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)
@@ -612,7 +613,7 @@ static int cgw_notifier(struct notifier_block *nb,
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct net *net = dev_net(dev);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 
 	if (msg == NETDEV_UNREGISTER) {
@@ -1163,7 +1164,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
 	if (!gwj->src.dev)
 		goto out;
 
-	if (gwj->src.dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(gwj->src.dev))
 		goto out;
 
 	gwj->dst.dev = __dev_get_by_index(net, gwj->ccgw.dst_idx);
@@ -1171,7 +1172,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
 	if (!gwj->dst.dev)
 		goto out;
 
-	if (gwj->dst.dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(gwj->dst.dev))
 		goto out;
 
 	/* is sending the skb back to the incoming interface intended? */
diff --git a/net/can/isotp.c b/net/can/isotp.c
index f5dc9d04bd686..17ff40a4708db 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -65,6 +65,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/can.h>
+#include <linux/can/can-ml.h>
 #include <linux/can/core.h>
 #include <linux/can/skb.h>
 #include <linux/can/isotp.h>
@@ -755,6 +756,14 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
 	if (skb->len != so->ll.mtu)
 		return;
 
+	/* check for correct CAN CC/FD frame content */
+	if (so->ll.mtu == CAN_MTU) {
+		if (!can_is_can_skb(skb))
+			return;
+	} else if (!can_is_canfd_skb(skb)) {
+		return;
+	}
+
 	cf = (struct canfd_frame *)skb->data;
 
 	/* if enabled: check reception of my configured extended address */
@@ -1479,16 +1488,17 @@ static int isotp_release(struct socket *sock)
 	/* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */
 	wake_up_interruptible(&so->wait);
 
+	rtnl_lock();
+
+	/* The netdev notifier chain runs under RTNL, so isotp_notifier() can't
+	 * be walking isotp_notifier_list and point to this socket. The spinlock
+	 * is still needed as isotp_init() adds sockets without holding RTNL.
+	 */
 	spin_lock(&isotp_notifier_lock);
-	while (isotp_busy_notifier == so) {
-		spin_unlock(&isotp_notifier_lock);
-		schedule_timeout_uninterruptible(1);
-		spin_lock(&isotp_notifier_lock);
-	}
+	WARN_ON_ONCE(isotp_busy_notifier == so);
 	list_del(&so->notifier);
 	spin_unlock(&isotp_notifier_lock);
 
-	rtnl_lock();
 	lock_sock(sk);
 
 	/* remove current filters & unregister
@@ -1496,11 +1506,11 @@ static int isotp_release(struct socket *sock)
 	 */
 	if (so->bound && so->dev) {
 		if (isotp_register_rxid(so))
-			can_rx_unregister(net, so->dev, so->rxid,
+			can_rx_unregister(dev_net(so->dev), so->dev, so->rxid,
 					  SINGLE_MASK(so->rxid),
 					  isotp_rcv, sk);
 
-		can_rx_unregister(net, so->dev, so->txid,
+		can_rx_unregister(dev_net(so->dev), so->dev, so->txid,
 				  SINGLE_MASK(so->txid),
 				  isotp_rcv_echo, sk);
 		netdev_put(so->dev, &so->dev_tracker);
@@ -1610,7 +1620,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
 		err = -ENODEV;
 		goto out;
 	}
-	if (dev->type != ARPHRD_CAN) {
+	if (!can_get_ml_priv(dev)) {
 		err = -ENODEV;
 		goto out_put_dev;
 	}
@@ -1625,14 +1635,14 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
 
 	if (isotp_register_rxid(so))
 		can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
-				isotp_rcv, sk, "isotp", sk);
+				isotp_rcv, sk, sock_i_ino(sk), sk);
 
 	/* no consecutive frame echo skb in flight */
 	WRITE_ONCE(so->cfecho, 0);
 
 	/* register for echo skb's */
 	can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
-			isotp_rcv_echo, sk, "isotpe", sk);
+			isotp_rcv_echo, sk, sock_i_ino(sk), sk);
 
 	/* switch to new settings */
 	so->ifindex = ifindex;
@@ -1897,7 +1907,7 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
 		return NOTIFY_DONE;
diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
index 5e5e6c228f225..d9384cf0e356f 100644
--- a/net/can/j1939/main.c
+++ b/net/can/j1939/main.c
@@ -184,7 +184,7 @@ static int j1939_can_rx_register(struct j1939_priv *priv)
 
 	j1939_priv_get(priv);
 	ret = can_rx_register(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
-			      j1939_can_recv, priv, "j1939", NULL);
+			      j1939_can_recv, priv, 0, NULL);
 	if (ret < 0) {
 		j1939_priv_put(priv);
 		return ret;
diff --git a/net/can/proc.c b/net/can/proc.c
index de4d05ae34597..64994ab485414 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -76,16 +76,39 @@ static const char rx_list_name[][8] = {
  * af_can statistics stuff
  */
 
+static void can_reset_pkg_stats(struct can_pkg_stats *pkg_stats)
+{
+	atomic_long_set(&pkg_stats->rx_frames, 0);
+	atomic_long_set(&pkg_stats->tx_frames, 0);
+	atomic_long_set(&pkg_stats->matches, 0);
+
+	pkg_stats->total_rx_rate = 0;
+	pkg_stats->total_tx_rate = 0;
+	pkg_stats->total_rx_match_ratio = 0;
+
+	pkg_stats->current_rx_rate = 0;
+	pkg_stats->current_tx_rate = 0;
+	pkg_stats->current_rx_match_ratio = 0;
+
+	pkg_stats->max_rx_rate = 0;
+	pkg_stats->max_tx_rate = 0;
+	pkg_stats->max_rx_match_ratio = 0;
+
+	atomic_long_set(&pkg_stats->rx_frames_delta, 0);
+	atomic_long_set(&pkg_stats->tx_frames_delta, 0);
+	atomic_long_set(&pkg_stats->matches_delta, 0);
+}
+
 static void can_init_stats(struct net *net)
 {
 	struct can_pkg_stats *pkg_stats = net->can.pkg_stats;
 	struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats;
 	/*
-	 * This memset function is called from a timer context (when
+	 * This stats reset is called from a timer context (when
 	 * can_stattimer is active which is the default) OR in a process
 	 * context (reading the proc_fs when can_stattimer is disabled).
 	 */
-	memset(pkg_stats, 0, sizeof(struct can_pkg_stats));
+	can_reset_pkg_stats(pkg_stats);
 	pkg_stats->jiffies_init = jiffies;
 
 	rcv_lists_stats->stats_reset++;
@@ -192,25 +215,27 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
 
 	hlist_for_each_entry_rcu(r, rx_list, list) {
 		char *fmt = (r->can_id & CAN_EFF_FLAG)?
-			"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\n" :
-			"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\n";
+			"  %6s  %08x  %08x  %8ld  %10llu" :
+			"  %6s     %03x    %08x  %8ld  %10llu";
 
 		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
-			   r->func, r->data, atomic_long_read(&r->matches),
-			   r->ident);
+			   atomic_long_read(&r->matches), r->ino);
+
+		/* without kallsyms %ps would print the raw text address */
+		if (IS_ENABLED(CONFIG_KALLSYMS))
+			seq_printf(m, "  %ps\n", r->func);
+		else
+			seq_puts(m, "  (unknown)\n");
 	}
 }
 
 static void can_print_recv_banner(struct seq_file *m)
 {
 	/*
-	 *                  can1.  00000000  00000000  00000000
-	 *                 .......          0  tp20
+	 *    device   can_id   can_mask   matches  sock_inode  function
+	 *     vcan0     000    00000000         0       43798  raw_rcv [can_raw]
 	 */
-	if (IS_ENABLED(CONFIG_64BIT))
-		seq_puts(m, "  device   can_id   can_mask      function          userdata       matches  ident\n");
-	else
-		seq_puts(m, "  device   can_id   can_mask  function  userdata   matches  ident\n");
+	seq_puts(m, "  device   can_id   can_mask   matches  sock_inode  function\n");
 }
 
 static int can_stats_proc_show(struct seq_file *m, void *v)
diff --git a/net/can/raw.c b/net/can/raw.c
index 0acd4f6c6dd67..d95ce54a4c458 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -226,7 +226,7 @@ static int raw_enable_filters(struct net *net, struct net_device *dev,
 	for (i = 0; i < count; i++) {
 		err = can_rx_register(net, dev, filter[i].can_id,
 				      filter[i].can_mask,
-				      raw_rcv, sk, "raw", sk);
+				      raw_rcv, sk, sock_i_ino(sk), sk);
 		if (err) {
 			/* clean up successfully registered filters */
 			while (--i >= 0)
@@ -247,7 +247,7 @@ static int raw_enable_errfilter(struct net *net, struct net_device *dev,
 
 	if (err_mask)
 		err = can_rx_register(net, dev, 0, err_mask | CAN_ERR_FLAG,
-				      raw_rcv, sk, "raw", sk);
+				      raw_rcv, sk, sock_i_ino(sk), sk);
 
 	return err;
 }
@@ -348,7 +348,7 @@ static int raw_notifier(struct notifier_block *nb, unsigned long msg,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
 		return NOTIFY_DONE;
@@ -422,16 +422,17 @@ static int raw_release(struct socket *sock)
 	ro = raw_sk(sk);
 	net = sock_net(sk);
 
+	rtnl_lock();
+
+	/* The netdev notifier chain runs under RTNL, so raw_notifier() can't
+	 * be walking raw_notifier_list and point to this socket. The spinlock
+	 * is still needed as raw_init() adds sockets without holding RTNL.
+	 */
 	spin_lock(&raw_notifier_lock);
-	while (raw_busy_notifier == ro) {
-		spin_unlock(&raw_notifier_lock);
-		schedule_timeout_uninterruptible(1);
-		spin_lock(&raw_notifier_lock);
-	}
+	WARN_ON_ONCE(raw_busy_notifier == ro);
 	list_del(&ro->notifier);
 	spin_unlock(&raw_notifier_lock);
 
-	rtnl_lock();
 	lock_sock(sk);
 
 	/* remove current filters & unregister */
@@ -491,7 +492,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
 			err = -ENODEV;
 			goto out;
 		}
-		if (dev->type != ARPHRD_CAN) {
+		if (!can_get_ml_priv(dev)) {
 			err = -ENODEV;
 			goto out_put_dev;
 		}
@@ -529,8 +530,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
 		ro->bound = 1;
 		/* bind() ok -> hold a reference for new ro->dev */
 		ro->dev = dev;
-		if (ro->dev)
-			netdev_hold(ro->dev, &ro->dev_tracker, GFP_KERNEL);
+		netdev_hold(ro->dev, &ro->dev_tracker, GFP_KERNEL);
 	}
 
 out_put_dev:

3/2 2026/10/15 04:32 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 61866
							output: 29
							thoughts: 2095
						

Thoughts:
**Patch Series Analysis: CAN Subsystem Deep Dive**

Okay, so I've been handed a patch series at HEAD, and my immediate instinct is to figure out the scope of changes and, critically, if there are any potential fuzzing targets.  Let's break this down.

First, I see a slew of modifications across the CAN subsystem.  We've got new device tree bindings, which is always a good start for a review, but also removals of old device bindings. The real meat, though, is in the driver and networking code: *a new file, bindings for can and changes to old ones, plus a deletion of the softing driver* .

My attention is immediately drawn to the core networking code. There are changes in `net/can/af_can.c`, `net/can/bcm.c`, `net/can/raw.c`, `net/can/isotp.c`, `net/can/gw.c`, and `net/can/proc.c`, which tells me the network stack is getting some love. And the core skb code is also heavily modified, specifically the handling of `dev_kfree_skb_any`.

I see some significant restructuring of locking in `bcm_release`, `isotp_release`, and `raw_release`. They've eliminated the busy loop and rearranged RTNL and socket locks and added `WARN_ON_ONCE`. This is good to see; these are often areas prone to subtle race conditions, and changes here warrant extremely careful scrutiny.

Importantly, I note a pattern change from `dev->type != ARPHRD_CAN` to `!can_get_ml_priv(dev)` in multiple files, including af_can, bcm, gw, isotp, and raw. This is something I'll need to understand in detail and verify for correctness; a seemingly small change can have wide repercussions.

Thinking about attack surface, and the fact that we've got CAN devices, sockets, and various USB drivers, including those from Kvaser and EMS, I'm already thinking about different entry points. Virtual CAN devices are accessible from userspace. It's also worth noting that USB drivers open the door for both raw-gadget, USB-fuzzing or standard virtio/emulated USB vulnerabilities. All of this screams "WorthFuzzing = true".

Now, I need to get my hands dirty. It is time to run some greps and verify this patch series very carefully, identifying the exact symbols impacted and confirming the required CONFIG options. This is where the real work begins.



4/2 2026/10/15 04:33 tool grepper
0m Args:
{
  "Expression": "config CAN",
  "PathPrefixes": [
    "net/can/Kconfig"
  ]
}

Results:
{
  "Output": "net/can/Kconfig-5-\nnet/can/Kconfig:6:menuconfig CAN\nnet/can/Kconfig-7-\ttristate \"CAN bus subsystem support\"\n--\nnet/can/Kconfig=22=if CAN\nnet/can/Kconfig-23-\nnet/can/Kconfig:24:config CAN_RAW\nnet/can/Kconfig-25-\ttristate \"Raw CAN Protocol (raw access with CAN-ID filtering)\"\n--\nnet/can/Kconfig-33-\nnet/can/Kconfig:34:config CAN_BCM\nnet/can/Kconfig-35-\ttristate \"Broadcast Manager CAN Protocol (with content filtering)\"\n--\nnet/can/Kconfig-45-\nnet/can/Kconfig:46:config CAN_GW\nnet/can/Kconfig-47-\ttristate \"CAN Gateway/Router (with netlink configuration)\"\n--\nnet/can/Kconfig=57=source \"net/can/j1939/Kconfig\"\nnet/can/Kconfig-58-\nnet/can/Kconfig:59:config CAN_ISOTP\nnet/can/Kconfig-60-\ttristate \"ISO 15765-2 CAN transport protocol\"\n"
}

5/2 2026/10/15 04:33 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 64857
							output: 47
							thoughts: 60
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Examining CAN Subsystem Configuration Options**

Alright, let's dive in. First, I need to get a clear picture of the CAN subsystem configuration. I'm going to start by reviewing the core options, specifically looking at `CAN`, `CAN_RAW`, `CAN_BCM`, `CAN_ISOTP`, `CAN_GW`, `CAN_VCAN`, and `CAN_DEV`. I want to immediately get a mental model of what's enabled, disabled, or built as modules. My goal is to quickly understand the flexibility and potential issues there.

Now, to dig a bit deeper, I'll hone in on `CAN_DEV` and `CAN_VCAN`. Let's see how these are defined within the drivers. I'll use `grep` in `drivers/net/can/Kconfig` to pin down the dependencies, help statements, and default configurations associated with those, and their interactions with the other CAN modules. This will tell me if there are any constraints or implications for the VCAN device specifically. I'm looking for anything that might impact its performance, stability, or compatibility with other CAN implementations. I'm expecting to find conditional dependencies, configuration options that influence the feature set, or maybe even potential conflicts.



6/2 2026/10/15 04:33 tool grepper
0m Args:
{
  "Expression": "config CAN_VCAN|config CAN_DEV|config CAN_KVASER_USB",
  "PathPrefixes": [
    "drivers/net/can/Kconfig"
  ]
}

Results:
{
  "Output": "drivers/net/can/Kconfig-2-\ndrivers/net/can/Kconfig:3:menuconfig CAN_DEV\ndrivers/net/can/Kconfig-4-\ttristate \"CAN Device Drivers\"\n--\ndrivers/net/can/Kconfig=23=if CAN_DEV\ndrivers/net/can/Kconfig-24-\ndrivers/net/can/Kconfig:25:config CAN_VCAN\ndrivers/net/can/Kconfig-26-\ttristate \"Virtual Local CAN Interface (vcan)\"\n"
}

7/2 2026/10/15 04:33 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 65384
							output: 38
							thoughts: 24
						

Thoughts:
Okay, here's my summary, tailored for an expert audience, presented as if it were my thought process:

**Diving into the Kvaser USB Driver Configuration**

Alright, I need to get to the bottom of this. Let's start with the usual suspects, and let's check `CAN_KVASER_USB`. Where would that be defined? Hmm, right, in the `drivers/net/can/usb/Kconfig` file. That's the logical place to begin digging into the Kvaser USB driver configuration. That Kconfig file will be the key to understanding the conditional compilation, dependencies, and any other relevant configurations associated with supporting Kvaser USB CAN interfaces. Let's see what we can learn there.



8/2 2026/10/15 04:33 tool grepper
0m Args:
{
  "Expression": "config CAN_KVASER_USB",
  "PathPrefixes": [
    "drivers/net/can/usb/Kconfig"
  ]
}

Results:
{
  "Output": "drivers/net/can/usb/Kconfig=54=config CAN_GS_USB\n--\ndrivers/net/can/usb/Kconfig-66-\ndrivers/net/can/usb/Kconfig:67:config CAN_KVASER_USB\ndrivers/net/can/usb/Kconfig-68-\ttristate \"Kvaser CAN/USB interface\"\n"
}

9/2 2026/10/15 04:33 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 65703
							output: 37
							thoughts: 810
						

Thoughts:
**Analyzing CANbus Subsystem Changes**

Okay, let's dive into these CANbus subsystem changes. I need to understand what's been modified in `net/can/af_can.c`, `net/can/bcm.c`, `net/can/isotp.c`, `net/can/raw.c`, `net/can/proc.c`, `net/can/gw.c`, `drivers/net/can/dev/skb.c`, and `drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c`. Ideally, I'd use `git log` to check the commit messages to understand the *why* of these changes, but I don't have that tool readily available. No worries, the diff is provided! I can examine it meticulously.

Focusing on `net/can/bcm.c` first, I see some interesting things:

*   The `bcm_proc_show` function has had a modification to its printing, I should check this later.
*   In `bcm_rx_setup`, the `can_rx_register` call now includes the socket inode number (`sock_i_ino(sk)`).
*   In `bcm_sendmsg` and `bcm_notifier`, there's a check `if (!can_get_ml_priv(dev))` instead of the previous `dev->type != ARPHRD_CAN`. Seems to be a more robust way to test a net device.
*   The `bcm_release` function's lock order has been changed. Previously, it had:
    *   Lock `bcm_notifier_lock`
    *   `while` loop with `bcm_busy_notifier`
    *   `list_del`
    *   Unlock `bcm_notifier_lock`
    *   Lock `sk`
    *   Then, later inside the function was `rtnl_lock()`
    Now it seems to be:
    *   Lock `sk`
    *   `release_sock(sk)`
    *   `rtnl_lock()`
    *   `spin_lock(&bcm_notifier_lock);`
    *   `list_del(&bo->notifier);`
    *   `spin_unlock(&bcm_notifier_lock);`
    *   `lock_sock(sk)`

    I see that the `rtnl_lock()` is now taken later in the function, it's before a `list_del` operation. I need to be sure about the lock order change, let me check the file version with `read-file` around line 1920. I need to get this straight, especially if this is related to concurrent access or locking issues.



10/2 2026/10/15 04:33 tool read-file
0m Args:
{
  "File": "net/can/bcm.c",
  "FirstLine": 1915,
  "LineCount": 85
}

Results:
{
  "Contents": "1915:\t{\n1916:\t\tstruct sock *sk = sock-\u003esk;\n1917:\t\tstruct net *net;\n1918:\t\tstruct bcm_sock *bo;\n1919:\t\tstruct bcm_op *op, *next;\n1920:\t\n1921:\t\tif (!sk)\n1922:\t\t\treturn 0;\n1923:\t\n1924:\t\tnet = sock_net(sk);\n1925:\t\tbo = bcm_sk(sk);\n1926:\t\n1927:\t\t/* remove bcm_ops, timer, rx_unregister(), etc. */\n1928:\t\n1929:\t\t/* Remove the procfs entry and the tx_ops before taking RTNL:\n1930:\t\t * remove_proc_entry() waits for concurrent readers of the entry and\n1931:\t\t * must not hold up RTNL for them. Clear bo-\u003ebcm_proc_read so that\n1932:\t\t * bcm_notify() does not remove the entry a second time.\n1933:\t\t */\n1934:\t\tlock_sock(sk);\n1935:\t\n1936:\t#if IS_ENABLED(CONFIG_PROC_FS)\n1937:\t\t/* remove procfs entry */\n1938:\t\tif (net-\u003ecan.bcmproc_dir \u0026\u0026 bo-\u003ebcm_proc_read) {\n1939:\t\t\tremove_proc_entry(bo-\u003eprocname, net-\u003ecan.bcmproc_dir);\n1940:\t\t\tbo-\u003ebcm_proc_read = NULL;\n1941:\t\t}\n1942:\t#endif /* CONFIG_PROC_FS */\n1943:\t\n1944:\t\tlist_for_each_entry_safe(op, next, \u0026bo-\u003etx_ops, list) {\n1945:\t\t\tlist_del_rcu(\u0026op-\u003elist);\n1946:\t\t\tbcm_remove_op(op);\n1947:\t\t}\n1948:\t\n1949:\t\trelease_sock(sk);\n1950:\t\n1951:\t\trtnl_lock();\n1952:\t\n1953:\t\t/* The netdev notifier chain runs under RTNL, so bcm_notifier() can't\n1954:\t\t * be walking bcm_notifier_list and point to this socket. The spinlock\n1955:\t\t * is still needed as bcm_init() adds sockets without holding RTNL.\n1956:\t\t */\n1957:\t\tspin_lock(\u0026bcm_notifier_lock);\n1958:\t\tWARN_ON_ONCE(bcm_busy_notifier == bo);\n1959:\t\tlist_del(\u0026bo-\u003enotifier);\n1960:\t\tspin_unlock(\u0026bcm_notifier_lock);\n1961:\t\n1962:\t\tlock_sock(sk);\n1963:\t\n1964:\t\tlist_for_each_entry_safe(op, next, \u0026bo-\u003erx_ops, list) {\n1965:\t\t\t/*\n1966:\t\t\t * Don't care if we're bound or not (due to netdev problems)\n1967:\t\t\t * can_rx_unregister() is always a save thing to do here.\n1968:\t\t\t */\n1969:\t\t\tif (op-\u003eifindex) {\n1970:\t\t\t\t/*\n1971:\t\t\t\t * Only remove subscriptions that had not\n1972:\t\t\t\t * been removed due to NETDEV_UNREGISTER\n1973:\t\t\t\t * in bcm_notifier()\n1974:\t\t\t\t *\n1975:\t\t\t\t * op-\u003erx_reg_dev is a tracked reference taken\n1976:\t\t\t\t * when the subscription was registered, so it\n1977:\t\t\t\t * stays valid here even if a concurrent\n1978:\t\t\t\t * NETDEV_UNREGISTER already unlisted the device.\n1979:\t\t\t\t */\n1980:\t\t\t\tif (op-\u003erx_reg_dev)\n1981:\t\t\t\t\tbcm_rx_unreg(op-\u003erx_reg_dev, op);\n1982:\t\t\t} else\n1983:\t\t\t\tcan_rx_unregister(net, NULL, op-\u003ecan_id,\n1984:\t\t\t\t\t\t  REGMASK(op-\u003ecan_id),\n1985:\t\t\t\t\t\t  bcm_rx_handler, op);\n1986:\t\n1987:\t\t}\n1988:\t\n1989:\t\trtnl_unlock();\n1990:\t\n1991:\t\tsynchronize_rcu();\n1992:\t\n1993:\t\tlist_for_each_entry_safe(op, next, \u0026bo-\u003erx_ops, list) {\n1994:\t\t\tlist_del_rcu(\u0026op-\u003elist);\n1995:\t\t\tbcm_remove_op(op);\n1996:\t\t}\n1997:\t\n1998:\t\t/* remove device reference */\n1999:\t\tif (bo-\u003ebound) {\n"
}

11/2 2026/10/15 04:33 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 68438
							output: 37
							thoughts: 70
						

Thoughts:
Here's a summary of my immediate observations:

**Initial Observations on Kernel Release Functions**

Okay, my initial scan reveals some interesting changes, specifically within `bcm_release`. I'm immediately drawn to the inclusion of `rtnl_lock` – that's a key detail to note. The presence of `WARN_ON_ONCE(bcm_busy_notifier == bo)` also catches my eye; it's likely a mechanism to detect and flag potential race conditions or resource contention within that busy notifier logic, which I'll want to investigate further.

Now, shifting gears, let's look at `isotp_release`. My gut tells me to check out `net/can/isotp.c` around line 1485. This might hold the answer to another issue, or at least some context. I'll take a quick dive to see what's happening there to better understand the kernel's behavior.



12/2 2026/10/15 04:33 tool read-file
0m Args:
{
  "File": "net/can/isotp.c",
  "FirstLine": 1480,
  "LineCount": 50
}

Results:
{
  "Contents": "1480:\t\t * claim can't race the forced ISOTP_SHUTDOWN below; force it\n1481:\t\t * unconditionally, even when a signal cut the wait above short\n1482:\t\t */\n1483:\t\tspin_lock_bh(\u0026so-\u003erx_lock);\n1484:\t\tWRITE_ONCE(so-\u003etx.state, ISOTP_SHUTDOWN);\n1485:\t\tspin_unlock_bh(\u0026so-\u003erx_lock);\n1486:\t\tWRITE_ONCE(so-\u003erx.state, ISOTP_IDLE);\n1487:\t\n1488:\t\t/* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */\n1489:\t\twake_up_interruptible(\u0026so-\u003ewait);\n1490:\t\n1491:\t\trtnl_lock();\n1492:\t\n1493:\t\t/* The netdev notifier chain runs under RTNL, so isotp_notifier() can't\n1494:\t\t * be walking isotp_notifier_list and point to this socket. The spinlock\n1495:\t\t * is still needed as isotp_init() adds sockets without holding RTNL.\n1496:\t\t */\n1497:\t\tspin_lock(\u0026isotp_notifier_lock);\n1498:\t\tWARN_ON_ONCE(isotp_busy_notifier == so);\n1499:\t\tlist_del(\u0026so-\u003enotifier);\n1500:\t\tspin_unlock(\u0026isotp_notifier_lock);\n1501:\t\n1502:\t\tlock_sock(sk);\n1503:\t\n1504:\t\t/* remove current filters \u0026 unregister\n1505:\t\t * tracked reference so-\u003edev is taken at bind() time with rtnl_lock\n1506:\t\t */\n1507:\t\tif (so-\u003ebound \u0026\u0026 so-\u003edev) {\n1508:\t\t\tif (isotp_register_rxid(so))\n1509:\t\t\t\tcan_rx_unregister(dev_net(so-\u003edev), so-\u003edev, so-\u003erxid,\n1510:\t\t\t\t\t\t  SINGLE_MASK(so-\u003erxid),\n1511:\t\t\t\t\t\t  isotp_rcv, sk);\n1512:\t\n1513:\t\t\tcan_rx_unregister(dev_net(so-\u003edev), so-\u003edev, so-\u003etxid,\n1514:\t\t\t\t\t  SINGLE_MASK(so-\u003etxid),\n1515:\t\t\t\t\t  isotp_rcv_echo, sk);\n1516:\t\t\tnetdev_put(so-\u003edev, \u0026so-\u003edev_tracker);\n1517:\t\t}\n1518:\t\n1519:\t\tso-\u003eifindex = 0;\n1520:\t\tso-\u003ebound = 0;\n1521:\t\tso-\u003edev = NULL;\n1522:\t\n1523:\t\trtnl_unlock();\n1524:\t\n1525:\t\t/* Always wait for a grace period before touching the timers below.\n1526:\t\t * A concurrent NETDEV_UNREGISTER may have already unregistered our\n1527:\t\t * filters and cleared so-\u003ebound in isotp_notify() without waiting\n1528:\t\t * for in-flight isotp_rcv() callers to finish, so this call must not\n1529:\t\t * be skipped just because so-\u003ebound is already 0 here.\n"
}

13/2 2026/10/15 04:33 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 69592
							output: 35
							thoughts: 28
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**Diving into the Raw CAN Socket Implementation**

Right, let's get down to brass tacks. I'm thinking, in the `raw_release` function, within the net/can/raw.c file, around line 420. The `raw_release` function is absolutely crucial for the lifecycle of a raw CAN socket, and I need to refresh my memory on the cleanup and resource handling that goes on there, right? I want to understand exactly what happens when the socket is closed or deallocated. Specifically, I'm probably looking for how resources like the socket's internal data structures, message buffers, any associated filters, or potentially even some reference counting are handled. It’s always the cleanup that's important; memory leaks or dangling pointers can be a nightmare in a networking context. So, let me just quickly glance at that section of the code and remind myself about all the relevant details.



14/2 2026/10/15 04:33 tool read-file
0m Args:
{
  "File": "net/can/raw.c",
  "FirstLine": 415,
  "LineCount": 45
}

Results:
{
  "Contents": " 415:\t\tstruct sock *sk = sock-\u003esk;\n 416:\t\tstruct raw_sock *ro;\n 417:\t\tstruct net *net;\n 418:\t\n 419:\t\tif (!sk)\n 420:\t\t\treturn 0;\n 421:\t\n 422:\t\tro = raw_sk(sk);\n 423:\t\tnet = sock_net(sk);\n 424:\t\n 425:\t\trtnl_lock();\n 426:\t\n 427:\t\t/* The netdev notifier chain runs under RTNL, so raw_notifier() can't\n 428:\t\t * be walking raw_notifier_list and point to this socket. The spinlock\n 429:\t\t * is still needed as raw_init() adds sockets without holding RTNL.\n 430:\t\t */\n 431:\t\tspin_lock(\u0026raw_notifier_lock);\n 432:\t\tWARN_ON_ONCE(raw_busy_notifier == ro);\n 433:\t\tlist_del(\u0026ro-\u003enotifier);\n 434:\t\tspin_unlock(\u0026raw_notifier_lock);\n 435:\t\n 436:\t\tlock_sock(sk);\n 437:\t\n 438:\t\t/* remove current filters \u0026 unregister */\n 439:\t\tif (ro-\u003ebound) {\n 440:\t\t\tif (ro-\u003edev) {\n 441:\t\t\t\traw_disable_allfilters(dev_net(ro-\u003edev), ro-\u003edev, sk);\n 442:\t\t\t\tnetdev_put(ro-\u003edev, \u0026ro-\u003edev_tracker);\n 443:\t\t\t} else {\n 444:\t\t\t\traw_disable_allfilters(net, NULL, sk);\n 445:\t\t\t}\n 446:\t\t}\n 447:\t\n 448:\t\tif (ro-\u003ecount \u003e 1)\n 449:\t\t\tkfree(ro-\u003efilter);\n 450:\t\n 451:\t\tro-\u003eifindex = 0;\n 452:\t\tro-\u003ebound = 0;\n 453:\t\tro-\u003edev = NULL;\n 454:\t\tro-\u003ecount = 0;\n 455:\t\n 456:\t\tsock_orphan(sk);\n 457:\t\tsock-\u003esk = NULL;\n 458:\t\n 459:\t\trelease_sock(sk);\n"
}

15/2 2026/10/15 04:33 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 70493
							output: 34
							thoughts: 399
						

Thoughts:
**Analyzing Recent Kernel Changes in CAN Subsystem**

Okay, so I'm looking at these recent changes in the CAN subsystem, specifically in `net/can/raw.c`, `net/can/isotp.c`, and `net/can/bcm.c`. Immediately, I notice a significant shift in the locking order.  Previously, it seems `rtnl_lock()` was acquired *after* `raw_notifier_lock` (and similar notifier locks in the other files), and after the notifier was removed from the list in `raw.c`, `isotp.c`, `bcm.c`. Now, and this is the crucial point, `rtnl_lock()` is called *before* those notifier locks.  And each of those changes is accompanied by a new `WARN_ON_ONCE` assertion: `WARN_ON_ONCE(raw_busy_notifier == ro)`, `WARN_ON_ONCE(isotp_busy_notifier == so)`, and `WARN_ON_ONCE(bcm_busy_notifier == bo)`.  That's a red flag – a big one.

This new locking order combined with these assertions screams "potential race condition mitigation" or "tightening up invariants". Given the change, I strongly suspect a subtle race was found and is being addressed here.  The `WARN_ON_ONCE` indicates an invariant that *should* always hold true under normal operation, and now there's explicit runtime verification of that assumption.

Then, there's the second part of the patch. The code is replacing checks for `dev->type != ARPHRD_CAN` with `!can_get_ml_priv(dev)` in `net/can/af_can.c`, `bcm.c`, `gw.c`, `isotp.c`, and `raw.c`.  I need to understand what `can_get_ml_priv` actually *does*. What’s the implication of replacing the direct hardware type check with this new call? Is this a broader change for multi-link (ML) support or an attempt to unify some logic? I need to check the kernel definition of that function right now.

And of course, that little note about fuzzing: "NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED". This is a core practice.  Since these patches introduce *new* assertions and modify existing, reachable code paths, fuzzing is *absolutely* mandatory. Even if the developer *thinks* the invariant is sound, these assertions demand fuzzing. Someone needs to run the fuzzers, and I need to review the results when they come in.  I need to make a note to myself to check that this is being tracked properly in the kernel's fuzzing infrastructure.



16/2 2026/10/15 04:34 tool grepper
0m Args:
{
  "Expression": "can_get_ml_priv",
  "PathPrefixes": [
    "include/linux/can/"
  ]
}

Results:
{
  "Output": "include/linux/can/can-ml.h=68=struct can_ml_priv {\n--\ninclude/linux/can/can-ml.h-75-\ninclude/linux/can/can-ml.h:76:static inline struct can_ml_priv *can_get_ml_priv(struct net_device *dev)\ninclude/linux/can/can-ml.h-77-{\n--\ninclude/linux/can/can-ml.h=87=static inline bool can_cap_enabled(struct net_device *dev, u32 cap)\ninclude/linux/can/can-ml.h-88-{\ninclude/linux/can/can-ml.h:89:\tstruct can_ml_priv *can_ml = can_get_ml_priv(dev);\ninclude/linux/can/can-ml.h-90-\n--\ninclude/linux/can/can-ml.h=97=static inline void can_set_cap(struct net_device *dev, u32 cap)\ninclude/linux/can/can-ml.h-98-{\ninclude/linux/can/can-ml.h:99:\tstruct can_ml_priv *can_ml = can_get_ml_priv(dev);\ninclude/linux/can/can-ml.h-100-\n"
}

17/2 2026/10/15 04:34 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 71845
							output: 38
							thoughts: 26
						

Thoughts:
Okay, let's dive into this. I'm going to take a look at the `include/linux/can/can-ml.h` header, specifically lines 65 through 105. I'm expecting to find the core definitions or structures related to the CAN Multi-Link (CAN-ML) functionality. Given the line range, I'm guessing this might cover the data structures used to manage multiple CAN controllers in a coordinated fashion, perhaps descriptors for message routing, or configuration related to the CAN-ML protocol itself. I anticipate this will involve a discussion about addressing schemes, device IDs, and message filtering if it's a newer implementation. I'll be looking for any hints on how the kernel handles the multiplexing of CAN frames across these multiple links. I'll need to parse the structures and identify their key members. I'm particularly interested in seeing how the message IDs, data length codes (DLC), and any other relevant fields are utilized in this multi-link context. Let's see if this lines up with my expectations.



18/2 2026/10/15 04:34 tool read-file
0m Args:
{
  "File": "include/linux/can/can-ml.h",
  "FirstLine": 65,
  "LineCount": 40
}

Results:
{
  "Contents": "  65:\t\tint entries;\n  66:\t};\n  67:\t\n  68:\tstruct can_ml_priv {\n  69:\t\tstruct can_dev_rcv_lists dev_rcv_lists;\n  70:\t#ifdef CAN_J1939\n  71:\t\tstruct j1939_priv *j1939_priv;\n  72:\t#endif\n  73:\t\tu32 can_cap;\n  74:\t};\n  75:\t\n  76:\tstatic inline struct can_ml_priv *can_get_ml_priv(struct net_device *dev)\n  77:\t{\n  78:\t\treturn netdev_get_ml_priv(dev, ML_PRIV_CAN);\n  79:\t}\n  80:\t\n  81:\tstatic inline void can_set_ml_priv(struct net_device *dev,\n  82:\t\t\t\t\t   struct can_ml_priv *ml_priv)\n  83:\t{\n  84:\t\tnetdev_set_ml_priv(dev, ml_priv, ML_PRIV_CAN);\n  85:\t}\n  86:\t\n  87:\tstatic inline bool can_cap_enabled(struct net_device *dev, u32 cap)\n  88:\t{\n  89:\t\tstruct can_ml_priv *can_ml = can_get_ml_priv(dev);\n  90:\t\n  91:\t\tif (!can_ml)\n  92:\t\t\treturn false;\n  93:\t\n  94:\t\treturn (can_ml-\u003ecan_cap \u0026 cap);\n  95:\t}\n  96:\t\n  97:\tstatic inline void can_set_cap(struct net_device *dev, u32 cap)\n  98:\t{\n  99:\t\tstruct can_ml_priv *can_ml = can_get_ml_priv(dev);\n 100:\t\n 101:\t\tcan_ml-\u003ecan_cap = cap;\n 102:\t}\n 103:\t\n 104:\t#endif /* CAN_ML_H */\n"
}

19/2 2026/10/15 04:34 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 72676
							output: 36
							thoughts: 2075
						

Thoughts:
**CAN Core Concurrency and Feature Focus for Fuzzing**

Alright, let's break this down. There's been a noticeable shift in the CAN core. The old `dev->type != ARPHRD_CAN` check has been replaced by `!can_get_ml_priv(dev)`, which hints at a more nuanced device type handling, likely related to Multi-Layer protocols. I'm also seeing changes in `drivers/net/can/dev/skb.c`, specifically in `can_dropped_invalid_skb`, where CANXL frames are now validated against capabilities, and the move from `kfree_skb` to `dev_kfree_skb_any` for more robust memory management, which I like. Also in `can_put_echo_skb`, again, `dev_kfree_skb_any`, and a crucial bound check!

The `isotp_rcv` function in `isotp.c` now includes explicit checks to ensure frame content matches CAN or CAN FD format, enforcing protocol compliance. I'm also seeing changes to stats.

Importantly, `can_rx_register`'s signature has changed, with the `ident` string replaced by a `u64 ino`. This inode is then printed in `/proc/net/can/rcvlist_*`, providing better tracking of registered receivers. We now have `can_reset_pkg_stats` replacing `memset`, indicating concern for atomic operations and non-zero-initialized values.

The USB CAN driver (`kvaser_usb`) shows updates in command length verification and command size functions.

Okay, so all this code is definitely reachable.  We can open CAN sockets with `SOCK_RAW`, `SOCK_DGRAM`, or `CAN_ISOTP`. We can create virtual CAN devices with `vcan` or `vxcan`. Frames can flow through sockets. We can read from proc files. We can bring interfaces up/down, which triggers netdev notifiers! We can close sockets, triggering release functions while netdev notifiers are firing. This is crucial: the netdev notifier vs. release concurrency is *exactly* what those `WARN_ON_ONCE` checks in `bcm_release`, `isotp_release`, and `raw_release` are addressing! As that comment explains, the notifier chain runs under RTNL. That lock is to prevent concurrent execution.  That `WARN_ON_ONCE` indicates a critical concurrency change!

This is a classic concurrency and locking invariant change with that new `WARN_ON_ONCE` macro!

Therefore, this whole area is prime for fuzzing: `WorthFuzzing = true`.

Now, according to the instructions, I need to identify key functions for the fuzzer:

Focusing on the guidance, I need to avoid ubiquitous lifecycle hot-paths (memory allocators, synchronization primitives) and focus on specific feature logic and entrypoints. Considering that the majority of changes involve the socket release and notifier functions, I need to focus there.

Here's the breakdown of what I'm seeing and the functions to focus on:

**Focus Symbols:**

*   **Concurrency/Locking Related:**
    *   `bcm_release` (Modified: Locking, Procfs, WARN_ON_ONCE)
    *   `raw_release` (Modified: Locking, WARN_ON_ONCE)
    *   `isotp_release` (Modified: Locking, WARN_ON_ONCE)

*   **Core Feature and Entrypoints:**
    *   `isotp_rcv` (Modified: CAN/CANFD frame check)
    *   `can_rx_register` (Modified: signature change)
    *   `can_dropped_invalid_skb` (Modified: CANXL, memory)
    *   `can_put_echo_skb` (Modified: Bounds check, memory)
    *   `kvaser_usb_hydra_read_bulk_callback` (Modified: Command Length verification)
    *   `kvaser_usb_hydra_verify_cmd_size`
    *   `kvaser_usb_hydra_cmd_size_rx`
    *   `bcm_rx_setup` (Modified: sock_i_ino passed to can_rx_register)
    *   `raw_enable_filters` (Modified: sock_i_ino passed to can_rx_register)
    *   `raw_enable_errfilter` (Modified: sock_i_ino passed)
    *   `isotp_bind` (Modified: sock_i_ino passed to can_rx_register)
    *   `cgw_register_filter` (Modified


20/2 2026/10/15 04:34 tool grepper
0m Args:
{
  "Expression": "EXPORT_SYMBOL.*can_",
  "PathPrefixes": [
    "net/can/af_can.c"
  ]
}

Results:
{
  "Output": "net/can/af_can.c=89=void can_sock_destruct(struct sock *sk)\n--\nnet/can/af_can.c-93-}\nnet/can/af_can.c:94:EXPORT_SYMBOL(can_sock_destruct);\nnet/can/af_can.c-95-\n--\nnet/can/af_can.c=202=int can_send(struct sk_buff *skb, int loop)\n--\nnet/can/af_can.c-300-}\nnet/can/af_can.c:301:EXPORT_SYMBOL(can_send);\nnet/can/af_can.c-302-\n--\nnet/can/af_can.c=444=int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,\n--\nnet/can/af_can.c-487-}\nnet/can/af_can.c:488:EXPORT_SYMBOL(can_rx_register);\nnet/can/af_can.c-489-\n--\nnet/can/af_can.c=513=void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,\n--\nnet/can/af_can.c-570-}\nnet/can/af_can.c:571:EXPORT_SYMBOL(can_rx_unregister);\nnet/can/af_can.c-572-\n--\nnet/can/af_can.c=644=void can_set_skb_uid(struct can_skb_ext *csx)\n--\nnet/can/af_can.c-648-}\nnet/can/af_can.c:649:EXPORT_SYMBOL(can_set_skb_uid);\nnet/can/af_can.c-650-\n--\nnet/can/af_can.c=769=int can_proto_register(const struct can_proto *cp)\n--\nnet/can/af_can.c-798-}\nnet/can/af_can.c:799:EXPORT_SYMBOL(can_proto_register);\nnet/can/af_can.c-800-\n--\nnet/can/af_can.c=805=void can_proto_unregister(const struct can_proto *cp)\n--\nnet/can/af_can.c-817-}\nnet/can/af_can.c:818:EXPORT_SYMBOL(can_proto_unregister);\nnet/can/af_can.c-819-\n"
}

21/2 2026/10/15 04:34 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 76472
							output: 38
							thoughts: 345
						

Thoughts:
**Analyzing CAN Bus Driver Symbols**

Okay, let's take a look at these symbols within the `net/can/` directory. I've got: `bcm_release`, `bcm_notifier`, `bcm_rx_setup`, `bcm_connect`, `bcm_sendmsg`, `raw_release`, `raw_notifier`, `raw_bind`, `isotp_release`, `isotp_notifier`, `isotp_rcv`, `isotp_bind`, `can_rx_register`, `can_rx_unregister`, `can_send`, `can_rcv`, `canfd_rcv`, `canxl_rcv`, `can_dropped_invalid_skb`, `can_put_echo_skb`, and `kvaser_usb_hydra_read_bulk_callback`. I need to figure out their scope and how they're exposed.

Specifically, I need to check the visibility of `bcm_release`, `raw_release`, and `isotp_release`. I know these are crucial in the socket operations and I want to determine if they're static.

Looking at `net/can/bcm.c`, I see `bcm_release` defined as `static int bcm_release(struct socket *sock)`. The fact that it's `static` is important. Since it's assigned to `bcm_ops.release = bcm_release`, the compiler *should* emit a symbol for it in the symbol table. Unless, of course, the build has enabled whole-program optimization (LTO) which might inline it, but that's not typical in a standard kernel build since it's a function pointer. I can assume the same logic will apply to `raw_release` and `isotp_release`, given their similar context.



22/2 2026/10/15 04:34 tool grepper
0m Args:
{
  "Expression": "bcm_release|raw_release|isotp_release",
  "PathPrefixes": [
    "net/can/"
  ]
}

Results:
{
  "Output": "net/can/bcm.c=1891=static int bcm_init(struct sock *sk)\n--\nnet/can/bcm.c-1913- */\nnet/can/bcm.c:1914:static int bcm_release(struct socket *sock)\nnet/can/bcm.c-1915-{\n--\nnet/can/bcm.c=2126=static const struct proto_ops bcm_ops = {\nnet/can/bcm.c-2127-\t.family        = PF_CAN,\nnet/can/bcm.c:2128:\t.release       = bcm_release,\nnet/can/bcm.c-2129-\t.bind          = sock_no_bind,\n--\nnet/can/isotp.c=1117=static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)\n--\nnet/can/isotp.c-1309-\tif (READ_ONCE(so-\u003etx.state) == ISOTP_SHUTDOWN) {\nnet/can/isotp.c:1310:\t\t/* isotp_release() has since taken over and already drained\nnet/can/isotp.c-1311-\t\t * our timers - don't send into a socket that's going away\n--\nnet/can/isotp.c-1355-\t\t * - complete transmission of current PDU\nnet/can/isotp.c:1356:\t\t * - shutdown state change in isotp_release()\nnet/can/isotp.c-1357-\t\t * isotp_tx_gen_done() uses common tx.state/tx_gen read sequence\n--\nnet/can/isotp.c-1363-\nnet/can/isotp.c:1364:\t\t/* still our claim, but isotp_release() force-shut it down */\nnet/can/isotp.c-1365-\t\tif (smp_load_acquire(\u0026so-\u003etx.state) == ISOTP_SHUTDOWN \u0026\u0026\n--\nnet/can/isotp.c-1405-\nnet/can/isotp.c:1406:\t/* only claim to IDLE if isotp_release() has not taken over */\nnet/can/isotp.c-1407-\tif (READ_ONCE(so-\u003etx.state) != ISOTP_SHUTDOWN)\n--\nnet/can/isotp.c=1415=static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,\n--\nnet/can/isotp.c-1458-\nnet/can/isotp.c:1459:static int isotp_release(struct socket *sock)\nnet/can/isotp.c-1460-{\n--\nnet/can/isotp.c=1548=static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len)\n--\nnet/can/isotp.c-1652-\nnet/can/isotp.c:1653:\t/* bind() ok -\u003e hold a reference for so-\u003edev so that isotp_release()\nnet/can/isotp.c-1654-\t * can safely reach the device later, even if a concurrent\n--\nnet/can/isotp.c=2020=static const struct proto_ops isotp_ops = {\nnet/can/isotp.c-2021-\t.family = PF_CAN,\nnet/can/isotp.c:2022:\t.release = isotp_release,\nnet/can/isotp.c-2023-\t.bind = isotp_bind,\n--\nnet/can/raw.c=377=static int raw_init(struct sock *sk)\n--\nnet/can/raw.c-412-\nnet/can/raw.c:413:static int raw_release(struct socket *sock)\nnet/can/raw.c-414-{\n--\nnet/can/raw.c=1072=static const struct proto_ops raw_ops = {\nnet/can/raw.c-1073-\t.family        = PF_CAN,\nnet/can/raw.c:1074:\t.release       = raw_release,\nnet/can/raw.c-1075-\t.bind          = raw_bind,\n"
}

23/2 2026/10/15 04:34 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 78359
							output: 36
							thoughts: 165
						

Thoughts:
**Examining CAN Configuration Options**

Okay, let's dive into these CAN configurations. My initial approach is always to check the Kconfig files, starting with `net/can/Kconfig`. I'm seeing `menuconfig CAN`, which is the high-level control. Then I'm mentally parsing the sub-configs: `config CAN_RAW`, `config CAN_BCM`, `config CAN_GW`, `config CAN_ISOTP`, and `config CAN_J1939`. These are the core protocol implementations, obviously.

Next, I need to look deeper. Let's move on to `drivers/net/can/Kconfig`. I'm anticipating device-specific configurations here, which I see with `menuconfig CAN_DEV`. Further configurations, specifically with `config CAN_VCAN` and `config CAN_VXCAN`, and I am noting those.

Finally, I'll go one level deeper, now with `drivers/net/can/usb/Kconfig`. My instinct is that I'll find USB-specific hardware support, and I'm correct in my assessment with `config CAN_KVASER_USB`.

My next step will be to confirm the dependencies for CAN, CAN_RAW, CAN_BCM, CAN_GW, and CAN_ISOTP. I'll need to go back to `net/can/Kconfig` to do that. These dependencies are key to understanding the build structure and how different components interact.



24/2 2026/10/15 04:34 tool grepper
0m Args:
{
  "Expression": "(config|menuconfig|depends on)",
  "PathPrefixes": [
    "net/can/Kconfig"
  ]
}

Results:
{
  "Output": "net/can/Kconfig-2-#\nnet/can/Kconfig:3:# Controller Area Network (CAN) network layer core configuration\nnet/can/Kconfig-4-#\nnet/can/Kconfig-5-\nnet/can/Kconfig:6:menuconfig CAN\nnet/can/Kconfig-7-\ttristate \"CAN bus subsystem support\"\n--\nnet/can/Kconfig=22=if CAN\nnet/can/Kconfig-23-\nnet/can/Kconfig:24:config CAN_RAW\nnet/can/Kconfig-25-\ttristate \"Raw CAN Protocol (raw access with CAN-ID filtering)\"\n--\nnet/can/Kconfig-33-\nnet/can/Kconfig:34:config CAN_BCM\nnet/can/Kconfig-35-\ttristate \"Broadcast Manager CAN Protocol (with content filtering)\"\n--\nnet/can/Kconfig-45-\nnet/can/Kconfig:46:config CAN_GW\nnet/can/Kconfig:47:\ttristate \"CAN Gateway/Router (with netlink configuration)\"\nnet/can/Kconfig-48-\tdefault y\n--\nnet/can/Kconfig-53-\t  CAN frames can be routed between CAN network interfaces (one hop).\nnet/can/Kconfig:54:\t  They can be modified with AND/OR/XOR/SET operations as configured\nnet/can/Kconfig:55:\t  by the netlink configuration interface known e.g. from iptables.\nnet/can/Kconfig-56-\nnet/can/Kconfig:57:source \"net/can/j1939/Kconfig\"\nnet/can/Kconfig-58-\nnet/can/Kconfig:59:config CAN_ISOTP\nnet/can/Kconfig-60-\ttristate \"ISO 15765-2 CAN transport protocol\"\n"
}

25/2 2026/10/15 04:34 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 79336
							output: 34
							thoughts: 21
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Investigating CAN Configuration Dependencies**

Alright, let's dive right in. My initial thought process is to quickly determine the dependencies associated with the CAN configuration options. Specifically, I need to check the `net/Kconfig` file. This is the standard location for kernel configuration options, and I need to see what pre-requisites, if any, the `menuconfig CAN` entry might have. This is usually the quickest way to understand the relationships between different kernel features and identify any potential conflicts or required enabling of other components before CAN can be properly configured. Knowing this will help me move forward with whatever task I have at hand.



26/2 2026/10/15 04:34 tool grepper
0m Args:
{
  "Expression": "source \"net/can/Kconfig\"",
  "PathPrefixes": [
    "net/Kconfig"
  ]
}

Results:
{
  "Output": "net/Kconfig=413=endmenu # Networking options\nnet/Kconfig-414-\nnet/Kconfig:415:source \"net/can/Kconfig\"\nnet/Kconfig-416-source \"net/bluetooth/Kconfig\"\n"
}

27/2 2026/10/15 04:34 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 79615
							output: 34
							thoughts: 110
						

Thoughts:
**Navigating the CAN Configuration Options**

Okay, so I need to configure CAN support. Right, `menuconfig CAN` is the entry point, and that lives in `net/can/Kconfig`. That makes sense; it's a network-related module, and `net/can/Kconfig` is pulled in from `net/Kconfig`, under the `if NET` condition. So that means I need to make sure both `NET` and `CAN` are enabled. Good, good.

Now, within the CAN configuration itself, I see a bunch of options: `CAN_RAW`, `CAN_BCM`, `CAN_ISOTP`, `CAN_GW`, `CAN_DEV`, `CAN_VCAN`, and `CAN_KVASER_USB`. I'm particularly interested in `CAN_DEV`, so I'll need to check the details for that. I think that lives in `drivers/net/can/Kconfig`, so I'll go check there.



28/2 2026/10/15 04:35 tool grepper
0m Args:
{
  "Expression": "menuconfig CAN_DEV",
  "PathPrefixes": [
    "drivers/net/can/Kconfig"
  ]
}

Results:
{
  "Output": "drivers/net/can/Kconfig-2-\ndrivers/net/can/Kconfig:3:menuconfig CAN_DEV\ndrivers/net/can/Kconfig-4-\ttristate \"CAN Device Drivers\"\n"
}

29/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 80032
							output: 34
							thoughts: 22
						

Thoughts:
Here's my analysis of the provided text, summarized in the first person, assuming I'm an expert in embedded systems and Linux kernel networking:

**Diving into the CAN Bus Configuration**

Okay, so I'm looking at `drivers/net/can/Kconfig`, specifically the first 30 lines. Right off the bat, I know this is the configuration file for the Controller Area Network (CAN) bus drivers within the Linux kernel. It's the gatekeeper that determines which CAN-related features and drivers get compiled into the kernel image. I need to understand this section thoroughly. I already have a mental model of the structure of Kconfig files, I just need to see how it's implemented in this case.

I'm expecting to see definitions related to enabling CAN core support, different CAN hardware driver options (likely including popular chips like MCP2515, SJA1000, maybe even newer SOC integrated CAN controllers), and perhaps some general CAN network configuration parameters. I'll be looking for `bool`, `tristate`, `select`, and `depends on` statements to understand the dependencies and build options. It's probable there'll be several `menuconfig` blocks and `config` symbols, with their respective help text, describing the various CAN-related features and drivers. I'm keen to find out about CAN FD support. I'm hoping to get a quick overview of how the different CAN drivers are organized. I need to ensure there are no obvious omissions in this configuration file. I hope I don't run into any obvious circular dependencies. Let's see what gems are hidden in this section.



30/2 2026/10/15 04:35 tool read-file
0m Args:
{
  "File": "drivers/net/can/Kconfig",
  "FirstLine": 1,
  "LineCount": 30
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0-only\n   2:\t\n   3:\tmenuconfig CAN_DEV\n   4:\t\ttristate \"CAN Device Drivers\"\n   5:\t\tdefault y\n   6:\t\tdepends on CAN\n   7:\t\thelp\n   8:\t\t  Controller Area Network (CAN) is serial communications protocol up to\n   9:\t\t  1Mbit/s for its original release (now known as Classical CAN) and up\n  10:\t\t  to 8Mbit/s for the more recent CAN with Flexible Data-Rate\n  11:\t\t  (CAN-FD). The CAN bus was originally mainly for automotive, but is now\n  12:\t\t  widely used in marine (NMEA2000), industrial, and medical\n  13:\t\t  applications. More information on the CAN network protocol family\n  14:\t\t  PF_CAN is contained in \u003cDocumentation/networking/can.rst\u003e.\n  15:\t\n  16:\t\t  This section contains all the CAN(-FD) device drivers including the\n  17:\t\t  virtual ones. If you own such devices or plan to use the virtual CAN\n  18:\t\t  interfaces to develop applications, say Y here.\n  19:\t\n  20:\t\t  To compile as a module, choose M here: the module will be called\n  21:\t\t  can-dev.\n  22:\t\n  23:\tif CAN_DEV\n  24:\t\n  25:\tconfig CAN_VCAN\n  26:\t\ttristate \"Virtual Local CAN Interface (vcan)\"\n  27:\t\thelp\n  28:\t\t  Similar to the network loopback devices, vcan offers a\n  29:\t\t  virtual local CAN interface.\n  30:\t\n"
}

31/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 80865
							output: 38
							thoughts: 12
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it's my own internal dialogue:

**Checking `CAN_KVASER_USB`**

Alright, let's take a look at `CAN_KVASER_USB`. That variable immediately flags a specific hardware dependency, likely related to interfacing with a Kvaser CAN interface over USB. Given the context, I'm probably troubleshooting something related to CAN bus communication. The presence of this variable likely means the code base has been architected with the expectation that Kvaser devices are present or, at the very least, considered as a potential interface. I need to understand its current state and how it's being used. Is it a compile-time flag, a runtime configuration setting, or a preprocessor directive? Is it defined, and if so, to what value? Is it a boolean? Is it tied to error handling, conditional code paths, or driver selection? The answer to these questions determines how it is being used within the system. My first thought is to use my IDE's search or grep function to see where it is defined, declared, and used. I'm looking for the logic that hinges on this setting. Depending on the answer, it's either going to provide critical information, or it will be a red herring!



32/2 2026/10/15 04:35 tool grepper
0m Args:
{
  "Expression": "config CAN_KVASER_USB",
  "PathPrefixes": [
    "drivers/net/can/usb/Kconfig"
  ]
}

Results:
{
  "Output": "drivers/net/can/usb/Kconfig=54=config CAN_GS_USB\n--\ndrivers/net/can/usb/Kconfig-66-\ndrivers/net/can/usb/Kconfig:67:config CAN_KVASER_USB\ndrivers/net/can/usb/Kconfig-68-\ttristate \"Kvaser CAN/USB interface\"\n"
}

33/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 81295
							output: 37
							thoughts: 22
						

Thoughts:
Here's my summary, as if I were thinking these thoughts:

**Examining the CAN-USB Driver Configuration**

Okay, let's dive in. I need to refresh my memory on the CAN-USB driver configuration options. I'm going to pull up the `drivers/net/can/usb/Kconfig` file, specifically around line 67. I expect to find the core configuration options that define the functionality of these drivers. I'm looking for things like which chips are supported, any specific hardware features that are enabled by default, and how they relate to the CAN bus interface. This is my starting point to understand the configuration landscape.



34/2 2026/10/15 04:35 tool read-file
0m Args:
{
  "File": "drivers/net/can/usb/Kconfig",
  "FirstLine": 60,
  "LineCount": 20
}

Results:
{
  "Contents": "  60:\t\t  (https://github.com/candle-usb/candleLight_fw) USB/CAN\n  61:\t\t  interfaces.\n  62:\t\n  63:\t\t  If unsure choose N,\n  64:\t\t  choose Y for built in support,\n  65:\t\t  M to compile as module (module will be named: gs_usb).\n  66:\t\n  67:\tconfig CAN_KVASER_USB\n  68:\t\ttristate \"Kvaser CAN/USB interface\"\n  69:\t\tselect NET_DEVLINK\n  70:\t\thelp\n  71:\t\t  This driver adds support for Kvaser CAN/USB devices like Kvaser\n  72:\t\t  Leaf Light, Kvaser USBcan II and Kvaser Memorator Pro 5xHS.\n  73:\t\n  74:\t\t  The driver provides support for the following devices:\n  75:\t\t    - Kvaser Leaf Light\n  76:\t\t    - Kvaser Leaf Professional HS\n  77:\t\t    - Kvaser Leaf SemiPro HS\n  78:\t\t    - Kvaser Leaf Professional LS\n  79:\t\t    - Kvaser Leaf Professional SWC\n"
}

35/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 81793
							output: 32
							thoughts: 50
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience, and written as if they were my own:

**Investigating the KVASER USB Dependency**

Alright, so `CAN_KVASER_USB` *obviously* depends on `USB`. It's pretty clear just looking at the config file structure—the Kconfig within `drivers/net/can/usb` is guarded by USB. But let's be thorough and confirm this, because we need to consider this dependency tree. Let me just quickly pull up `drivers/net/can/usb/Kconfig` to verify the exact nature of that dependency and confirm there isn't anything *else* we should be aware of. We need to be solid on the implications here.



36/2 2026/10/15 04:35 tool grepper
0m Args:
{
  "Expression": "USB",
  "PathPrefixes": [
    "drivers/net/can/usb/Kconfig"
  ]
}

Results:
{
  "Output": "drivers/net/can/usb/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/can/usb/Kconfig:2:menu \"CAN USB interfaces\"\ndrivers/net/can/usb/Kconfig:3:\tdepends on USB\ndrivers/net/can/usb/Kconfig-4-\ndrivers/net/can/usb/Kconfig:5:config CAN_8DEV_USB\ndrivers/net/can/usb/Kconfig:6:\ttristate \"8 devices USB2CAN interface\"\ndrivers/net/can/usb/Kconfig-7-\thelp\ndrivers/net/can/usb/Kconfig:8:\t  This driver supports the USB2CAN interface\ndrivers/net/can/usb/Kconfig-9-\t  from 8 devices (http://www.8devices.com).\ndrivers/net/can/usb/Kconfig-10-\ndrivers/net/can/usb/Kconfig:11:config CAN_EMS_USB\ndrivers/net/can/usb/Kconfig:12:\ttristate \"EMS CPC-USB/ARM7 CAN/USB interface\"\ndrivers/net/can/usb/Kconfig-13-\thelp\ndrivers/net/can/usb/Kconfig:14:\t  This driver is for the one channel CPC-USB/ARM7 CAN/USB interface\ndrivers/net/can/usb/Kconfig-15-\t  from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).\ndrivers/net/can/usb/Kconfig-16-\ndrivers/net/can/usb/Kconfig:17:config CAN_ESD_USB\ndrivers/net/can/usb/Kconfig:18:\ttristate \"esd electronics gmbh CAN/USB interfaces\"\ndrivers/net/can/usb/Kconfig-19-\thelp\ndrivers/net/can/usb/Kconfig:20:\t  This driver adds support for several CAN/USB interfaces\ndrivers/net/can/usb/Kconfig-21-\t  from esd electronics gmbh (https://www.esd.eu).\n--\ndrivers/net/can/usb/Kconfig-23-\t  The drivers supports the following devices:\ndrivers/net/can/usb/Kconfig:24:\t    - esd CAN-USB/2\ndrivers/net/can/usb/Kconfig:25:\t    - esd CAN-USB/3-FD\ndrivers/net/can/usb/Kconfig:26:\t    - esd CAN-USB/Micro\ndrivers/net/can/usb/Kconfig-27-\n--\ndrivers/net/can/usb/Kconfig=31=config CAN_ETAS_ES58X\ndrivers/net/can/usb/Kconfig:32:\ttristate \"ETAS ES58X CAN/USB interfaces\"\ndrivers/net/can/usb/Kconfig-33-\tselect CRC16\n--\ndrivers/net/can/usb/Kconfig=42=config CAN_F81604\ndrivers/net/can/usb/Kconfig:43:        tristate \"Fintek F81604 USB to 2CAN interface\"\ndrivers/net/can/usb/Kconfig-44-        help\ndrivers/net/can/usb/Kconfig:45:          This driver supports the Fintek F81604 USB to 2CAN interface.\ndrivers/net/can/usb/Kconfig-46-          The device can support CAN2.0A/B protocol and also support\n--\ndrivers/net/can/usb/Kconfig-53-\ndrivers/net/can/usb/Kconfig:54:config CAN_GS_USB\ndrivers/net/can/usb/Kconfig-55-\ttristate \"Geschwister Schneider UG and candleLight compatible interfaces\"\n--\ndrivers/net/can/usb/Kconfig-59-\t  bytewerk.org candleLight compatible\ndrivers/net/can/usb/Kconfig:60:\t  (https://github.com/candle-usb/candleLight_fw) USB/CAN\ndrivers/net/can/usb/Kconfig-61-\t  interfaces.\n--\ndrivers/net/can/usb/Kconfig-66-\ndrivers/net/can/usb/Kconfig:67:config CAN_KVASER_USB\ndrivers/net/can/usb/Kconfig:68:\ttristate \"Kvaser CAN/USB interface\"\ndrivers/net/can/usb/Kconfig-69-\tselect NET_DEVLINK\ndrivers/net/can/usb/Kconfig-70-\thelp\ndrivers/net/can/usb/Kconfig:71:\t  This driver adds support for Kvaser CAN/USB devices like Kvaser\ndrivers/net/can/usb/Kconfig:72:\t  Leaf Light, Kvaser USBcan II and Kvaser Memorator Pro 5xHS.\ndrivers/net/can/usb/Kconfig-73-\n--\ndrivers/net/can/usb/Kconfig-83-\t    - Kvaser Memorator II HS/HS\ndrivers/net/can/usb/Kconfig:84:\t    - Kvaser USBcan Professional HS/HS\ndrivers/net/can/usb/Kconfig-85-\t    - Kvaser Leaf Light GI\n--\ndrivers/net/can/usb/Kconfig-89-\t    - Kvaser BlackBird SemiPro\ndrivers/net/can/usb/Kconfig:90:\t    - Kvaser USBcan R\ndrivers/net/can/usb/Kconfig:91:\t    - Kvaser USBcan R v2\ndrivers/net/can/usb/Kconfig-92-\t    - Kvaser Leaf Light v2\n--\ndrivers/net/can/usb/Kconfig-96-\t    - Kvaser Mini PCIe 1xCAN\ndrivers/net/can/usb/Kconfig:97:\t    - Kvaser USBcan Light 2xHS\ndrivers/net/can/usb/Kconfig:98:\t    - Kvaser USBcan II HS/HS\ndrivers/net/can/usb/Kconfig:99:\t    - Kvaser USBcan II HS/LS\ndrivers/net/can/usb/Kconfig:100:\t    - Kvaser USBcan Rugged (\"USBcan Rev B\")\ndrivers/net/can/usb/Kconfig-101-\t    - Kvaser Memorator HS/HS\n--\ndrivers/net/can/usb/Kconfig-113-\t    - Kvaser Memorator Pro 5xHS\ndrivers/net/can/usb/Kconfig:114:\t    - Kvaser USBcan Light 4xHS\ndrivers/net/can/usb/Kconfig:115:\t    - Kvaser USBcan Pro 2xHS v2\ndrivers/net/can/usb/Kconfig:116:\t    - Kvaser USBcan Pro 4xHS\ndrivers/net/can/usb/Kconfig:117:\t    - Kvaser USBcan Pro 5xCAN\ndrivers/net/can/usb/Kconfig:118:\t    - Kvaser USBcan Pro 5xHS\ndrivers/net/can/usb/Kconfig-119-\t    - Kvaser U100\n--\ndrivers/net/can/usb/Kconfig-122-\t    - ATI Memorator Pro 2xHS v2\ndrivers/net/can/usb/Kconfig:123:\t    - ATI USBcan Pro 2xHS v2\ndrivers/net/can/usb/Kconfig-124-\t    - Vining 800\n--\ndrivers/net/can/usb/Kconfig-130-\ndrivers/net/can/usb/Kconfig:131:config CAN_MCBA_USB\ndrivers/net/can/usb/Kconfig-132-\ttristate \"Microchip CAN BUS Analyzer interface\"\n--\ndrivers/net/can/usb/Kconfig=137=config CAN_NCT6694\n--\ndrivers/net/can/usb/Kconfig-142-\t  If you say yes to this option, support will be included for Nuvoton\ndrivers/net/can/usb/Kconfig:143:\t  NCT6694, a USB device to socket CANfd controller.\ndrivers/net/can/usb/Kconfig-144-\n--\ndrivers/net/can/usb/Kconfig-147-\ndrivers/net/can/usb/Kconfig:148:config CAN_PEAK_USB\ndrivers/net/can/usb/Kconfig:149:\ttristate \"PEAK PCAN-USB/USB Pro interfaces for CAN 2.0b/CAN-FD\"\ndrivers/net/can/usb/Kconfig-150-\thelp\ndrivers/net/can/usb/Kconfig:151:\t  This driver supports the PEAK-System Technik USB adapters that enable\ndrivers/net/can/usb/Kconfig-152-\t  access to the CAN bus, with respect to the CAN 2.0b and/or CAN-FD\n--\ndrivers/net/can/usb/Kconfig-154-\ndrivers/net/can/usb/Kconfig:155:\t  PCAN-USB             single CAN 2.0b channel USB adapter\ndrivers/net/can/usb/Kconfig:156:\t  PCAN-USB Pro         dual CAN 2.0b channels USB adapter\ndrivers/net/can/usb/Kconfig:157:\t  PCAN-USB FD          single CAN-FD channel USB adapter\ndrivers/net/can/usb/Kconfig:158:\t  PCAN-USB Pro FD      dual CAN-FD channels USB adapter\ndrivers/net/can/usb/Kconfig:159:\t  PCAN-Chip USB        CAN-FD to USB stamp module\ndrivers/net/can/usb/Kconfig:160:\t  PCAN-USB X6          6 CAN-FD channels USB adapter\ndrivers/net/can/usb/Kconfig-161-\n--\ndrivers/net/can/usb/Kconfig=164=config CAN_UCAN\n--\ndrivers/net/can/usb/Kconfig-167-\t  This driver supports the Theobroma Systems\ndrivers/net/can/usb/Kconfig:168:\t  UCAN USB-CAN interface.\ndrivers/net/can/usb/Kconfig-169-\ndrivers/net/can/usb/Kconfig:170:\t  The UCAN driver supports the microcontroller-based USB/CAN\ndrivers/net/can/usb/Kconfig-171-\t  adapters from Theobroma Systems. There are two form-factors\n--\ndrivers/net/can/usb/Kconfig-173-\ndrivers/net/can/usb/Kconfig:174:\t  * Seal: standalone USB stick\ndrivers/net/can/usb/Kconfig-175-\t          https://www.theobroma-systems.com/seal)\n"
}

37/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 84674
							output: 27
							thoughts: 37
						

Thoughts:
Okay, let's dive into this CAN driver configuration.

**Analyzing CAN Driver Configuration**

Alright, I need to verify something about the CAN driver's interaction with the proc filesystem. First, I need to check the relevant configuration files. Specifically, I should check the settings in `net/can/proc.c`. My immediate thought is, "Do we actually need `PROC_FS` defined to use `proc.c`?" This is a fundamental question of dependencies. Then, I need to cross-reference that with the top-level makefile to see how it's all put together. So, to ensure everything works as expected, I'll need to examine `net/can/Makefile` as well.



38/2 2026/10/15 04:35 tool grepper
0m Args:
{
  "Expression": "proc",
  "PathPrefixes": [
    "net/can/Makefile"
  ]
}

Results:
{
  "Output": "net/can/Makefile=7=can-y\t\t\t:= af_can.o\nnet/can/Makefile:8:can-$(CONFIG_PROC_FS)\t+= proc.o\nnet/can/Makefile-9-\n"
}

39/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 84952
							output: 49
							thoughts: 949
						

Thoughts:
**Focusing on Key Kernel Function Changes**

Okay, so I see we definitely need `PROC_FS` for `proc.o`, and `KALLSYMS` is used in `proc.c`, specifically with `IS_ENABLED(CONFIG_KALLSYMS)`.

Now, let's quickly review the configurations involved. I'm seeing: `CAN`, `CAN_RAW`, `CAN_BCM`, `CAN_ISOTP`, `CAN_GW`, `CAN_DEV`, `CAN_VCAN`, `CAN_KVASER_USB`, and of course `PROC_FS`.

My priority now is to identify very specific kernel functions that either directly implement or are exercising the altered logic. I need to zero in on the functions that are either new or have had significant changes. Let's see...

In the `net/can/` directory, I've got a list. I see that `bcm_release`, `raw_release`, and `isotp_release` have had their lock ordering modified, with new `WARN_ON_ONCE` checks to detect lock ordering issues. Then `isotp_rcv` has new MTU and frame content validation, using `can_is_can_skb` and `can_is_canfd_skb`.

Okay, there are some signature changes for `can_rx_register` and `can_rx_unregister`, `can_send`, `can_rcv`, `canfd_rcv`, `canxl_rcv`, and `cgw_create_job` which is important to keep in mind, and also note that the changes in `can_rx_register` and `bcm_rx_setup` and `raw_enable_filters` and `isotp_bind` pass `sock_i_ino` to `can_rx_register`.

`can_reset_pkg_stats` is a new helper function replacing `memset` in `proc.c`. `can_print_rcvlist` is updated to display inode and function symbol for the receiver list. Also note the checks for `!can_get_ml_priv` that are implemented.

Now, in `drivers/net/can/dev/skb.c`, there's a new check `!can_cap_enabled(dev, CAN_CAP_XL)` in `can_dropped_invalid_skb`, along with `dev_kfree_skb_any`. There are bounds check error handling with `dev_kfree_skb_any` in `can_put_echo_skb`.

Finally, in `drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c`, there's a lot of activity. `kvaser_usb_hydra_read_bulk_callback` is completely overhauled in parsing and validation. Also, there are new functions: `kvaser_usb_hydra_verify_cmd_size` which verifies command length, and `kvaser_usb_hydra_cmd_size_rx` for RX command size validation.

Let's check those last two functions, `kvaser_usb_hydra_verify_cmd_size` and `kvaser_usb_hydra_cmd_size_rx`, I need to make sure those are static, right? Yes, they are! It is important to know that `kvaser_usb_hydra_read_bulk_callback` is static too, being passed to a URB, or called from `kvaser_usb_read_bulk_callback`. So that's important to keep in mind.



40/2 2026/10/15 04:35 tool grepper
0m Args:
{
  "Expression": "kvaser_usb_hydra_read_bulk_callback",
  "PathPrefixes": [
    "drivers/net/can/usb/kvaser_usb/"
  ]
}

Results:
{
  "Output": "drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c=689=kvaser_usb_hydra_send_simple_cmd_async(struct kvaser_usb_net_priv *priv,\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-716-/* This function is used for synchronously waiting on hydra control commands.\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:717: * Note: Compared to kvaser_usb_hydra_read_bulk_callback(), we never need to\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-718- *       handle partial hydra commands. Since hydra control commands are always\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c=2135=static int kvaser_usb_hydra_flush_queue(struct kvaser_usb_net_priv *priv)\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2155- */\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2156:static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2157-\t\t\t\t\t\tvoid *buf, int len)\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c=2292=const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = {\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2310-\t.dev_flush_queue = kvaser_usb_hydra_flush_queue,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2311:\t.dev_read_bulk_callback = kvaser_usb_hydra_read_bulk_callback,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2312-\t.dev_frame_to_cmd = kvaser_usb_hydra_frame_to_cmd,\n"
}

41/2 2026/10/15 04:35 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 87369
							output: 30
							thoughts: 144
						

Thoughts:
**Analyzing Kvaser USB Hydra Module and CAN Package Statistics**

Okay, so `kvaser_usb_hydra_read_bulk_callback`... yes, that's a function pointer within the operational structure. Therefore, it *should* have a symbol defined within the module itself, which is what I suspected.

Now, let's pivot to the CAN subsystem. I need to understand how package statistics are handled. Specifically, I'm interested in `can_reset_pkg_stats` in `net/can/proc.c`. First question: is it static? Let me double-check... Yes, line 79 confirms it: `static void can_reset_pkg_stats(...)`. Okay, it *is* static. That means its scope is limited, which is important for understanding potential side effects or dependencies.

Now, the natural follow-up is to understand where `can_reset_pkg_stats` is called from. It looks like the only call is from `can_init_stats(struct net *net)`. Excellent. So I need to now check if `can_init_stats` itself is static. Knowing this is key to understanding the full scope of stat resets.



42/2 2026/10/15 04:36 tool grepper
0m Args:
{
  "Expression": "can_init_stats",
  "PathPrefixes": [
    "net/can/"
  ]
}

Results:
{
  "Output": "net/can/af_can.h=51=struct receiver {\n--\nnet/can/af_can.h-64-\nnet/can/af_can.h:65:/* can be reset e.g. by can_init_stats() */\nnet/can/af_can.h-66-struct can_pkg_stats {\n--\nnet/can/proc.c=79=static void can_reset_pkg_stats(struct can_pkg_stats *pkg_stats)\n--\nnet/can/proc.c-101-\nnet/can/proc.c:102:static void can_init_stats(struct net *net)\nnet/can/proc.c-103-{\n--\nnet/can/proc.c=138=void can_stat_update(struct timer_list *t)\n--\nnet/can/proc.c-152-\tif (user_reset)\nnet/can/proc.c:153:\t\tcan_init_stats(net);\nnet/can/proc.c-154-\n--\nnet/can/proc.c-156-\tif (j \u003c pkg_stats-\u003ejiffies_init)\nnet/can/proc.c:157:\t\tcan_init_stats(net);\nnet/can/proc.c-158-\n--\nnet/can/proc.c-160-\tif (rx_frames \u003e (LONG_MAX / HZ))\nnet/can/proc.c:161:\t\tcan_init_stats(net);\nnet/can/proc.c-162-\n--\nnet/can/proc.c-164-\tif (tx_frames \u003e (LONG_MAX / HZ))\nnet/can/proc.c:165:\t\tcan_init_stats(net);\nnet/can/proc.c-166-\n--\nnet/can/proc.c-168-\tif (matches \u003e (LONG_MAX / 100))\nnet/can/proc.c:169:\t\tcan_init_stats(net);\nnet/can/proc.c-170-\n--\nnet/can/proc.c=306=static int can_reset_stats_proc_show(struct seq_file *m, void *v)\n--\nnet/can/proc.c-318-\t\tif (pkg_stats-\u003ejiffies_init != jiffies)\nnet/can/proc.c:319:\t\t\tcan_init_stats(net);\nnet/can/proc.c-320-\n"
}

43/2 2026/10/15 04:36 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 88435
							output: 536
							thoughts: 1277
						

Thoughts:
**Analysis of CAN Subsystem Changes for Fuzzing Suitability**

Okay, let's break this down. The core concern here is whether these recent CAN subsystem modifications warrant inclusion in our fuzzing targets. I see that `can_stat_update` is a timer callback and `can_reset_stats_proc_show` is called from `/proc/net/can/reset_stats`. That's a starting point, but we need to dig deeper.

First, I need to pinpoint the critical functions where the actual code changes are. The FocusSymbols are my main interest. I need to focus on where the developers were changing the core logic, introducing new locks/assertions, or altering how data is handled. So I will go over them individually: `bcm_release`, `raw_release`, `isotp_release`, `isotp_rcv`, `isotp_bind`, `bcm_rx_setup`, `raw_enable_filters`, `can_rx_register`, `can_rx_unregister`, `can_send`, `can_rcv`, `canfd_rcv`, `canxl_rcv`, `can_dropped_invalid_skb`, `can_put_echo_skb`, `cgw_create_job`, and `kvaser_usb_hydra_read_bulk_callback`. I want to emphasize that these are all very specific and they are not related to any general lifecycle code that's used everywhere. These functions are where the actual changes were implemented.

Next, I need to ensure that the necessary kernel configurations are enabled for exercising these changes. I need to confirm: `CAN`, `CAN_RAW`, `CAN_BCM`, `CAN_ISOTP`, `CAN_GW`, `CAN_DEV`, `CAN_VCAN`, `CAN_KVASER_USB`, and `PROC_FS`. I'll quickly check the Kconfig dependencies to verify that we're covering all relevant dependencies.  I'm making sure `CAN_DEV` depends on `CAN`, `CAN_VCAN` depends on `CAN_DEV`, and the other protocols depend on CAN. Further, the Kvaser USB interface depends on USB and selects `NET_DEVLINK`. This ensures we are getting all the necessary parts.

Now, the crucial question: Is this WorthFuzzing? I need to build a solid justification. The changes touch core networking within `net/can/` (including locking refactoring, new assertions, MTU checks, CANXL validation, and socket lifecycle changes) and touch virtual device handling and USB device driver logic. All of this can be reached and executed in a standard QEMU environment. This implies that the attack surface has expanded, and we can easily explore the newly introduced code paths. Hence, **WorthFuzzing is definitively true**.

Let's synthesize my reasoning. The heart of the matter is the refactoring within the core CAN networking stack, namely `net/can/`. In `bcm_release()`, `isotp_release()`, and `raw_release()`, the locking strategy with `rtnl_lock()` and notifier spinlocks was refactored and new assertions were introduced. Device type validation across multiple files was modified. Frame validation was added in `isotp_rcv()`. Receiver tracking was updated in `can_rx_register()`. CAN-XL capabilities were checked in `can_dropped_invalid_skb()`, and message validation was overhauled in `kvaser_usb_hydra_read_bulk_callback()`. These components are all reachable via standard CAN sockets (`AF_CAN`: `CAN_RAW`, `CAN_BCM`, `CAN_ISOTP`), virtual CAN devices (`vcan`), CAN gateway netlink, and USB CAN emulation.

Finally, let me double-check the `set-results`:

*   `WorthFuzzing`: true (as stated)
*   `Reasoning`: Concise explanation of changes and their reachability
*   `FocusSymbols`: A complete list of target functions
*   `EnableConfigs`: A complete list of config symbols.

Everything is clear, precise, and satisfies the criteria. I'm ready to call `set-results`.



44/2 2026/10/15 04:36 tool set-results
0m Args:
{
  "EnableConfigs": [
    "CAN",
    "CAN_RAW",
    "CAN_BCM",
    "CAN_ISOTP",
    "CAN_GW",
    "CAN_DEV",
    "CAN_VCAN",
    "CAN_KVASER_USB",
    "PROC_FS"
  ],
  "FocusSymbols": [
    "bcm_release",
    "raw_release",
    "isotp_release",
    "isotp_rcv",
    "isotp_bind",
    "bcm_rx_setup",
    "raw_enable_filters",
    "can_rx_register",
    "can_rx_unregister",
    "can_send",
    "can_rcv",
    "canfd_rcv",
    "canxl_rcv",
    "can_dropped_invalid_skb",
    "can_put_echo_skb",
    "cgw_create_job",
    "kvaser_usb_hydra_read_bulk_callback"
  ],
  "Reasoning": "The patch series introduces significant changes and refactorings across the CAN core networking subsystem (net/can/) and CAN device drivers:\n1. Socket release \u0026 notifier concurrency refactoring: In bcm_release(), isotp_release(), and raw_release(), socket locking and notifier list removal were overhauled to serialize under RTNL, removing busy-wait loops and adding new WARN_ON_ONCE() runtime assertions to verify that notifiers are not concurrently executing on the socket being destroyed.\n2. Device validation: Checks for CAN device capability and mid-layer priv (can_get_ml_priv(dev)) replace ARPHRD_CAN checks across af_can, bcm, raw, isotp, and gw.\n3. Protocol and SKB handling: Added CAN-XL capability validation in can_dropped_invalid_skb(), updated frame content checking in isotp_rcv(), and improved bounds checking/skb freeing in can_put_echo_skb().\n4. USB driver packet parsing: In kvaser_usb_hydra, command size parsing and verification were overhauled to handle partial commands and validate command bounds.\n\nAll modified networking code is fully reachable in virtualized QEMU environments using standard CAN sockets (CAN_RAW, CAN_BCM, CAN_ISOTP), virtual netdevs (vcan), and USB fuzzing interfaces. Fuzzing is warranted to test the new locking invariants, assertions, and boundary checks.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "CAN",
    "CAN_RAW",
    "CAN_BCM",
    "CAN_ISOTP",
    "CAN_GW",
    "CAN_DEV",
    "CAN_VCAN",
    "CAN_KVASER_USB",
    "PROC_FS"
  ],
  "FocusSymbols": [
    "bcm_release",
    "raw_release",
    "isotp_release",
    "isotp_rcv",
    "isotp_bind",
    "bcm_rx_setup",
    "raw_enable_filters",
    "can_rx_register",
    "can_rx_unregister",
    "can_send",
    "can_rcv",
    "canfd_rcv",
    "canxl_rcv",
    "can_dropped_invalid_skb",
    "can_put_echo_skb",
    "cgw_create_job",
    "kvaser_usb_hydra_read_bulk_callback"
  ],
  "Reasoning": "The patch series introduces significant changes and refactorings across the CAN core networking subsystem (net/can/) and CAN device drivers:\n1. Socket release \u0026 notifier concurrency refactoring: In bcm_release(), isotp_release(), and raw_release(), socket locking and notifier list removal were overhauled to serialize under RTNL, removing busy-wait loops and adding new WARN_ON_ONCE() runtime assertions to verify that notifiers are not concurrently executing on the socket being destroyed.\n2. Device validation: Checks for CAN device capability and mid-layer priv (can_get_ml_priv(dev)) replace ARPHRD_CAN checks across af_can, bcm, raw, isotp, and gw.\n3. Protocol and SKB handling: Added CAN-XL capability validation in can_dropped_invalid_skb(), updated frame content checking in isotp_rcv(), and improved bounds checking/skb freeing in can_put_echo_skb().\n4. USB driver packet parsing: In kvaser_usb_hydra, command size parsing and verification were overhauled to handle partial commands and validate command bounds.\n\nAll modified networking code is fully reachable in virtualized QEMU environments using standard CAN sockets (CAN_RAW, CAN_BCM, CAN_ISOTP), virtual netdevs (vcan), and USB fuzzing interfaces. Fuzzing is warranted to test the new locking invariants, assertions, and boundary checks.",
  "WorthFuzzing": true
}

45/1 2026/10/15 04:36 action If
1m Args:
{
  "WorthFuzzing": true
}

Results:
null

46/2 2026/10/15 04:36 agent kmsan-evaluator
1m Model:
core

Args:
null

Results:
{
  "KMSANReasoning": "The patch series focuses on the Linux CAN subsystem and includes:\n1. Procfs formatting updates in net/can (replacing pointer formatting %pK with socket inode numbers and %ps symbol lookups, plus introducing can_reset_pkg_stats() to explicitly zero all fields of struct can_pkg_stats).\n2. Socket lifecycle and locking refactoring in BCM, Raw, and ISO-TP sockets (reordering RTNL vs notifier spinlock acquisitions to prevent deadlocks and race conditions).\n3. Packet bounds and length validation in drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c to ensure incoming USB command frames have sufficient bytes before parsing.\n4. Driver maintenance such as PM ops modernization (DEFINE_SIMPLE_DEV_PM_OPS), safe SKB freeing (dev_kfree_skb_any), reference count fixes (of_node_put, clk_put), and removal of the deprecated softing driver.\n5. In cc770_platform.c, fixing a logic bug where priv-\u003ecpu_interface was read before being assigned from platform data.\n\nNone of the changes introduce uninitialized stack or heap memory reads, struct padding leaks, or uninitialized kernel-to-user copy operations. The potential risks associated with these patches (deadlocks, use-after-free, out-of-bounds accesses) are already covered by LOCKDEP and standard KASAN. Therefore, a dedicated KMSAN session is not warranted.",
  "NeedsKMSAN": false
}

Instruction:
You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.

CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
  a comprehensive suite of debugging tools and sanitizers, including KASAN
  (out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
  (locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
  or page allocations) and kernel-to-user memory info-leaks.

Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.

Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.

Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
   attributes, ioctl output arguments, socket options, or BPF buffers) where fields
   or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
   or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
   could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
   uninitialized bytes of existing buffers.

Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
  dereferences, locking deadlocks, or use-after-free bugs (these are already caught
  by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
  or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.

Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit e266d8df68870dedf5e7f9fa0d4a7c435ea59542
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Oct 15 04:32:17 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml b/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml
new file mode 100644
index 0000000000000..d5cba5b1bac19
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/can/aeroflexgaisler,grcan.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aeroflex Gaisler GRCAN and GRHCAN CAN controllers
+
+maintainers:
+  - Marc Kleine-Budde <mkl@pengutronix.de>
+
+description: |
+  The GRCAN and GRHCAN CAN controllers are available in the GRLIB VHDL IP
+  core library.
+
+  On a LEON SPARC system there are no device tree source files. The nodes
+  are built by the PROM from the AMBA plug&play information, which does not
+  provide a compatible string. The driver therefore matches on the node
+  name, which is built as "<core name>@<irq>,<address>" from the "name" and
+  "reg" properties of the AMBA plug&play core.
+
+  The GRLIB build ID is not a property of the controller node either. It is
+  read from the "systemid" property of the "/ambapp0" node, and the TX bug
+  workaround is enabled when that property is absent or when its least
+  significant 16 bits are smaller than 4100.
+
+select:
+  properties:
+    $nodename:
+      pattern: '^(01_034|01_03d|GAISLER_GRCAN|GAISLER_GRHCAN)@'
+  required:
+    - $nodename
+
+properties:
+  reg:
+    maxItems: 1
+
+  freq:
+    description:
+      Frequency of the external oscillator clock in Hz, which is the
+      frequency of the AMBA bus in the ordinary case.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  interrupts:
+    maxItems: 1
+    description:
+      Interrupt number of the controller, as built from the AMBA plug&play
+      information.
+
+required:
+  - reg
+  - freq
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    /* AMBA plug&play children are named "<core name>@<irq>,<address>" */
+    GAISLER_GRCAN@c,80000000 {
+        reg = <0x80000000 0x1000>;
+        freq = <40000000>;
+        interrupts = <12>;
+    };
+...
diff --git a/Documentation/devicetree/bindings/net/can/grcan.txt b/Documentation/devicetree/bindings/net/can/grcan.txt
deleted file mode 100644
index 34ef3498f8870..0000000000000
--- a/Documentation/devicetree/bindings/net/can/grcan.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-Aeroflex Gaisler GRCAN and GRHCAN CAN controllers.
-
-The GRCAN and CRHCAN CAN controllers are available in the GRLIB VHDL IP core
-library.
-
-Note: These properties are built from the AMBA plug&play in a Leon SPARC system
-(the ordinary environment for GRCAN and GRHCAN). There are no dts files for
-sparc.
-
-Required properties:
-
-- name : Should be "GAISLER_GRCAN", "01_03d", "GAISLER_GRHCAN" or "01_034"
-
-- reg : Address and length of the register set for the device
-
-- freq : Frequency of the external oscillator clock in Hz (the frequency of
-	the amba bus in the ordinary case)
-
-- interrupts : Interrupt number for this device
-
-Optional properties:
-
-- systemid : If not present or if the value of the least significant 16 bits
-	of this 32-bit property is smaller than GRCAN_TXBUG_SAFE_GRLIB_VERSION
-	a bug workaround is activated.
-
-For further information look in the documentation for the GLIB IP core library:
-http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
index b9d9dd7a79676..4b94bc8d911be 100644
--- a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
@@ -13,6 +13,8 @@ properties:
   compatible:
     oneOf:
       - enum:
+          - renesas,r9a08g045-canfd        # RZ/G3S
+          - renesas,r9a08g046-canfd        # RZ/G3L
           - renesas,r9a09g047-canfd        # RZ/G3E
           - renesas,r9a09g077-canfd        # RZ/T2H
 
@@ -132,7 +134,9 @@ properties:
   power-domains:
     maxItems: 1
 
-  resets: true
+  resets:
+    minItems: 1
+    maxItems: 2
 
   reset-names:
     items:
@@ -185,8 +189,6 @@ required:
   - clocks
   - clock-names
   - power-domains
-  - assigned-clocks
-  - assigned-clock-rates
   - channel0
   - channel1
 
@@ -198,6 +200,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - renesas,r9a08g045-canfd
               - renesas,rzg2l-canfd
     then:
       properties:
@@ -209,7 +212,6 @@ allOf:
 
         resets:
           minItems: 2
-          maxItems: 2
 
   - if:
       properties:
@@ -231,6 +233,8 @@ allOf:
         resets:
           maxItems: 1
 
+        reset-names: false
+
   - if:
       properties:
         compatible:
@@ -246,7 +250,6 @@ allOf:
 
         resets:
           minItems: 2
-          maxItems: 2
 
   - if:
       properties:
@@ -266,6 +269,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - renesas,r9a08g045-canfd
               - renesas,r9a09g077-canfd
               - renesas,rcar-gen3-canfd
               - renesas,rzg2l-canfd
@@ -291,6 +295,25 @@ allOf:
       patternProperties:
         "^channel[6-7]$": false
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: renesas,r9a08g046-canfd
+    then:
+      properties:
+        interrupts:
+          minItems: 11
+
+        interrupt-names:
+          minItems: 11
+
+        resets:
+          minItems: 2
+
+      patternProperties:
+        "^channel[3-7]$": false
+
   - if:
       properties:
         compatible:
@@ -330,6 +353,7 @@ allOf:
         compatible:
           contains:
             enum:
+              - renesas,r9a08g045-canfd
               - renesas,r9a09g047-canfd
               - renesas,rzg2l-canfd
     then:
@@ -350,6 +374,22 @@ allOf:
       properties:
         reset-names: false
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - renesas,r9a08g045-canfd
+              - renesas,r9a08g046-canfd
+    then:
+      properties:
+        renesas,no-can-fd: false
+        renesas,fd-only: false
+    else:
+      required:
+        - assigned-clocks
+        - assigned-clock-rates
+
 unevaluatedProperties: false
 
 examples:
diff --git a/Documentation/networking/can.rst b/Documentation/networking/can.rst
index 536ff411da1d1..908c199cf6ada 100644
--- a/Documentation/networking/can.rst
+++ b/Documentation/networking/can.rst
@@ -1040,17 +1040,17 @@ As described in :ref:`socketcan-receive-lists` the SocketCAN core uses several f
 lists to deliver received CAN frames to CAN protocol modules. These
 receive lists, their filters and the count of filter matches can be
 checked in the appropriate receive list. All entries contain the
-device and a protocol module identifier::
+CAN network device and the subscribed function name::
 
     foo@bar:~$ cat /proc/net/can/rcvlist_all
 
     receive list 'rx_all':
-      (vcan3: no entry)
-      (vcan2: no entry)
-      (vcan1: no entry)
-      device   can_id   can_mask  function  userdata   matches  ident
-       vcan0     000    00000000  f88e6370  f6c6f400         0  raw
       (any: no entry)
+      device   can_id   can_mask   matches  sock_inode  function
+       vcan0     000    00000000         0       63586  raw_rcv [can_raw]
+      (vcan1: no entry)
+      (vcan2: no entry)
+      (vcan3: no entry)
 
 In this example an application requests any CAN traffic from vcan0::
 
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index a8fad6fe53020..fb16f67a99f99 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -254,7 +254,6 @@ source "drivers/net/can/peak_canfd/Kconfig"
 source "drivers/net/can/rcar/Kconfig"
 source "drivers/net/can/rockchip/Kconfig"
 source "drivers/net/can/sja1000/Kconfig"
-source "drivers/net/can/softing/Kconfig"
 source "drivers/net/can/spi/Kconfig"
 source "drivers/net/can/usb/Kconfig"
 
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 4010d17f85836..fa2cdd7bcd0ac 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -13,7 +13,6 @@ obj-y				+= rcar/
 obj-y				+= rockchip/
 obj-y				+= spi/
 obj-y				+= usb/
-obj-y				+= softing/
 
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_BXCAN)		+= bxcan.o
diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c
index 4bddd015775bc..622c5d73e33a8 100644
--- a/drivers/net/can/bxcan.c
+++ b/drivers/net/can/bxcan.c
@@ -1042,7 +1042,7 @@ static void bxcan_remove(struct platform_device *pdev)
 	free_candev(ndev);
 }
 
-static int __maybe_unused bxcan_suspend(struct device *dev)
+static int bxcan_suspend(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct bxcan_priv *priv = netdev_priv(ndev);
@@ -1059,7 +1059,7 @@ static int __maybe_unused bxcan_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused bxcan_resume(struct device *dev)
+static int bxcan_resume(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct bxcan_priv *priv = netdev_priv(ndev);
@@ -1076,7 +1076,7 @@ static int __maybe_unused bxcan_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(bxcan_pm_ops, bxcan_suspend, bxcan_resume);
 
 static const struct of_device_id bxcan_of_match[] = {
 	{.compatible = "st,stm32f4-bxcan"},
@@ -1087,7 +1087,7 @@ MODULE_DEVICE_TABLE(of, bxcan_of_match);
 static struct platform_driver bxcan_driver = {
 	.driver = {
 		.name = KBUILD_MODNAME,
-		.pm = &bxcan_pm_ops,
+		.pm = pm_sleep_ptr(&bxcan_pm_ops),
 		.of_match_table = bxcan_of_match,
 	},
 	.probe = bxcan_probe,
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index b6c4f02ffb97a..ac81670762c7c 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -137,11 +137,11 @@ static int cc770_get_platform_data(struct platform_device *pdev,
 	struct cc770_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
 	priv->can.clock.freq = pdata->osc_freq;
+	priv->cpu_interface = pdata->cir;
 	if (priv->cpu_interface & CPUIF_DSC)
 		priv->can.clock.freq /= 2;
 	priv->clkout = pdata->cor;
 	priv->bus_config = pdata->bcr;
-	priv->cpu_interface = pdata->cir;
 
 	return 0;
 }
@@ -156,10 +156,13 @@ static int cc770_platform_probe(struct platform_device *pdev)
 	int err, irq;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!mem || irq <= 0)
+	if (!mem)
 		return -ENODEV;
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
 	mem_size = resource_size(mem);
 	if (!request_mem_region(mem->start, mem_size, pdev->name))
 		return -EBUSY;
diff --git a/drivers/net/can/ctucanfd/ctucanfd.h b/drivers/net/can/ctucanfd/ctucanfd.h
index 0e9904f6a05d6..7dcd7dc507e49 100644
--- a/drivers/net/can/ctucanfd/ctucanfd.h
+++ b/drivers/net/can/ctucanfd/ctucanfd.h
@@ -76,7 +76,7 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr,
 			void (*set_drvdata_fnc)(struct device *dev,
 						struct net_device *ndev));
 
-int ctucan_suspend(struct device *dev) __maybe_unused;
-int ctucan_resume(struct device *dev) __maybe_unused;
+int ctucan_suspend(struct device *dev);
+int ctucan_resume(struct device *dev);
 
 #endif /*__CTUCANFD__*/
diff --git a/drivers/net/can/ctucanfd/ctucanfd_pci.c b/drivers/net/can/ctucanfd/ctucanfd_pci.c
index 4b6db28f7b670..9c9c41c3058c0 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c
@@ -259,7 +259,7 @@ static void ctucan_pci_remove(struct pci_dev *pdev)
 	kfree(bdata);
 }
 
-static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
 
 static const struct pci_device_id ctucan_pci_tbl[] = {
 	{PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21,
@@ -273,7 +273,7 @@ static struct pci_driver ctucan_pci_driver = {
 	.id_table = ctucan_pci_tbl,
 	.probe = ctucan_pci_probe,
 	.remove = ctucan_pci_remove,
-	.driver.pm = &ctucan_pci_pm_ops,
+	.driver.pm = pm_sleep_ptr(&ctucan_pci_pm_ops),
 };
 
 module_pci_driver(ctucan_pci_driver);
diff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c
index 70e2577c85416..4962b00ee8ac0 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_platform.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c
@@ -99,7 +99,7 @@ static void ctucan_platform_remove(struct platform_device *pdev)
 	free_candev(ndev);
 }
 
-static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);
 
 /* Match table for OF platform binding */
 static const struct of_device_id ctucan_of_match[] = {
@@ -114,7 +114,7 @@ static struct platform_driver ctucanfd_driver = {
 	.remove = ctucan_platform_remove,
 	.driver	= {
 		.name = DRV_NAME,
-		.pm = &ctucan_platform_pm_ops,
+		.pm = pm_sleep_ptr(&ctucan_platform_pm_ops),
 		.of_match_table	= ctucan_of_match,
 	},
 };
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 14edec5afb57e..738d5968dfa68 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
  */
 
+#include <linux/can/can-ml.h>
 #include <linux/can/dev.h>
 #include <linux/module.h>
 #include <net/can.h>
@@ -54,6 +55,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 	if (idx >= priv->echo_skb_max) {
 		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
 			   __func__, idx, priv->echo_skb_max);
+		dev_kfree_skb_any(skb);
 		return -EINVAL;
 	}
 
@@ -62,7 +64,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 	    (skb->protocol != htons(ETH_P_CAN) &&
 	     skb->protocol != htons(ETH_P_CANFD) &&
 	     skb->protocol != htons(ETH_P_CANXL))) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return 0;
 	}
 
@@ -90,7 +92,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 	} else {
 		/* locking problem with netif_stop_queue() ?? */
 		netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return -EBUSY;
 	}
 
@@ -227,7 +229,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
 
 	csx = can_skb_ext_add(skb);
 	if (!csx) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		goto out_error_cc;
 	}
 
@@ -258,7 +260,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
 
 	csx = can_skb_ext_add(skb);
 	if (!csx) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		goto out_error_fd;
 	}
 
@@ -296,7 +298,7 @@ struct sk_buff *alloc_canxl_skb(struct net_device *dev,
 
 	csx = can_skb_ext_add(skb);
 	if (!csx) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		goto out_error_xl;
 	}
 
@@ -388,7 +390,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
 		break;
 
 	case ETH_P_CANXL:
-		if (!can_is_canxl_skb(skb))
+		if (!can_cap_enabled(dev, CAN_CAP_XL) || !can_is_canxl_skb(skb))
 			goto inval_skb;
 		break;
 
@@ -402,7 +404,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
 	return false;
 
 inval_skb:
-	kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 	dev->stats.tx_dropped++;
 	return true;
 }
diff --git a/drivers/net/can/esd/esdacc.c b/drivers/net/can/esd/esdacc.c
index 73e66f9a3781c..05d41ed34a02e 100644
--- a/drivers/net/can/esd/esdacc.c
+++ b/drivers/net/can/esd/esdacc.c
@@ -62,14 +62,17 @@ static void acc_resetmode_leave(struct acc_core *core)
 	acc_resetmode_entered(core);
 }
 
-static void acc_txq_put(struct acc_core *core, u32 acc_id, u32 acc_dlc,
-			const void *data)
+static void acc_txq_put(struct acc_core *core, u32 acc_dlc, const void *data)
 {
 	acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_1,
 			   *((const u32 *)(data + 4)));
 	acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_0,
 			   *((const u32 *)data));
 	acc_write32(core, ACC_CORE_OF_TXFIFO_DLC, acc_dlc);
+}
+
+static void acc_txq_start(struct acc_core *core, u32 acc_id)
+{
 	/* CAN id must be written at last. This write starts TX. */
 	acc_write32(core, ACC_CORE_OF_TXFIFO_ID, acc_id);
 }
@@ -287,11 +290,12 @@ netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 		acc_id = cf->can_id & CAN_SFF_MASK;
 	}
 
-	can_put_echo_skb(skb, netdev, core->tx_fifo_head, 0);
+	acc_txq_put(core, acc_dlc, cf->data);
 
+	can_put_echo_skb(skb, netdev, core->tx_fifo_head, 0);
 	core->tx_fifo_head = acc_tx_fifo_next(core, tx_fifo_head);
 
-	acc_txq_put(core, acc_id, acc_dlc, cf->data);
+	acc_txq_start(core, acc_id);
 
 	return NETDEV_TX_OK;
 }
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 86b40abe9e767..30ae7c344a05e 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1986,6 +1986,7 @@ static int flexcan_setup_stop_mode_gpr(struct platform_device *pdev)
 		"gpr %s req_gpr=0x02%x req_bit=%u\n",
 		gpr_np->full_name, priv->stm.req_gpr, priv->stm.req_bit);
 
+	of_node_put(gpr_np);
 	return 0;
 
 out_put_node:
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index ce12fa6df56d5..1b4944d1d06dd 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -10,8 +10,8 @@
  * Full documentation of the GRCAN core can be found here:
  * http://www.gaisler.com/products/grlib/grip.pdf
  *
- * See "Documentation/devicetree/bindings/net/can/grcan.txt" for information on
- * open firmware properties.
+ * See "Documentation/devicetree/bindings/net/can/aeroflexgaisler,grcan.yaml"
+ * for information on open firmware properties.
  *
  * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
  * sysfs interface.
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
index d8c9bfb202304..a0597db720864 100644
--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
@@ -1739,6 +1739,7 @@ static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
 			iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 			kvaser_pciefd_pwm_stop(can);
 			kvaser_pciefd_devlink_port_unregister(can);
+			timer_shutdown_sync(&can->bec_poll_timer);
 			free_candev(can->can.dev);
 		}
 	}
@@ -1879,7 +1880,7 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)
 		struct kvaser_pciefd_can *can = pcie->can[i];
 
 		unregister_candev(can->can.dev);
-		timer_delete(&can->bec_poll_timer);
+		timer_shutdown_sync(&can->bec_poll_timer);
 		kvaser_pciefd_pwm_stop(can);
 		kvaser_pciefd_devlink_port_unregister(can);
 	}
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index d11a7c88fc32f..d31179312026b 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -169,17 +169,17 @@ static void m_can_pci_remove(struct pci_dev *pci)
 	pci_free_irq_vectors(pci);
 }
 
-static __maybe_unused int m_can_pci_suspend(struct device *dev)
+static int m_can_pci_suspend(struct device *dev)
 {
 	return m_can_class_suspend(dev);
 }
 
-static __maybe_unused int m_can_pci_resume(struct device *dev)
+static int m_can_pci_resume(struct device *dev)
 {
 	return m_can_class_resume(dev);
 }
 
-static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
+static DEFINE_SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
 			 m_can_pci_suspend, m_can_pci_resume);
 
 static const struct pci_device_id m_can_pci_id_table[] = {
@@ -195,7 +195,7 @@ static struct pci_driver m_can_pci_driver = {
 	.remove = m_can_pci_remove,
 	.id_table = m_can_pci_id_table,
 	.driver = {
-		.pm = &m_can_pci_pm_ops,
+		.pm = pm_sleep_ptr(&m_can_pci_pm_ops),
 	},
 };
 
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index fcc37b73ed436..c643879673680 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -132,9 +132,9 @@
 #define RCANFD_CCTR_BEIE		BIT(8)
 #define RCANFD_CCTR_CSLPR		BIT(2)
 #define RCANFD_CCTR_CHMDC_MASK		(0x3)
-#define RCANFD_CCTR_CHDMC_COPM		(0x0)
-#define RCANFD_CCTR_CHDMC_CRESET	(0x1)
-#define RCANFD_CCTR_CHDMC_CHLT		(0x2)
+#define RCANFD_CCTR_CHMDC_COPM		(0x0)
+#define RCANFD_CCTR_CHMDC_CRESET	(0x1)
+#define RCANFD_CCTR_CHMDC_CHLT		(0x2)
 
 /* RSCFDnCFDCmSTS / RSCFDnCmSTS */
 #define RCANFD_CSTS_COMSTS		BIT(7)
@@ -436,7 +436,6 @@ struct rcar_canfd_hw_info {
 	u8 rnc_field_width;
 	u8 max_aflpn;
 	u8 max_cftml;
-	u8 max_channels;
 	u8 postdiv;
 	/* hardware features */
 	unsigned shared_global_irqs:1;	/* Has shared global irqs */
@@ -444,6 +443,8 @@ struct rcar_canfd_hw_info {
 	unsigned ch_interface_mode:1;	/* Has channel interface mode */
 	unsigned shared_can_regs:1;	/* Has shared classical can registers */
 	unsigned external_clk:1;	/* Has external clock */
+	unsigned fcan_pclk:1;		/* Has fcan sourced from pclk. */
+	unsigned fixed_canfd:1;		/* Has mode fixed to canfd. */
 };
 
 /* Channel priv data */
@@ -476,6 +477,7 @@ struct rcar_canfd_global {
 	struct reset_control *rstc1;
 	struct reset_control *rstc2;
 	const struct rcar_canfd_hw_info *info;
+	u8 max_channels;
 };
 
 /* CAN FD mode nominal rate constants */
@@ -611,12 +613,13 @@ static const struct rcar_canfd_hw_info rcar_gen3_hw_info = {
 	.rnc_field_width = 8,
 	.max_aflpn = 31,
 	.max_cftml = 15,
-	.max_channels = 2,
 	.postdiv = 2,
 	.shared_global_irqs = 1,
 	.ch_interface_mode = 0,
 	.shared_can_regs = 0,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {
@@ -628,12 +631,13 @@ static const struct rcar_canfd_hw_info rcar_gen4_hw_info = {
 	.rnc_field_width = 16,
 	.max_aflpn = 127,
 	.max_cftml = 31,
-	.max_channels = 8,
 	.postdiv = 2,
 	.shared_global_irqs = 1,
 	.ch_interface_mode = 1,
 	.shared_can_regs = 1,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 static const struct rcar_canfd_hw_info rzg2l_hw_info = {
@@ -645,12 +649,32 @@ static const struct rcar_canfd_hw_info rzg2l_hw_info = {
 	.rnc_field_width = 8,
 	.max_aflpn = 31,
 	.max_cftml = 15,
-	.max_channels = 2,
 	.postdiv = 1,
 	.multi_channel_irqs = 1,
 	.ch_interface_mode = 0,
 	.shared_can_regs = 0,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
+};
+
+static const struct rcar_canfd_hw_info r9a08g045_hw_info = {
+	.nom_bittiming = &rcar_canfd_gen4_nom_bittiming_const,
+	.data_bittiming = &rcar_canfd_gen4_data_bittiming_const,
+	.tdc_const = &rcar_canfd_gen4_tdc_const,
+	.regs = &rcar_gen4_regs,
+	.sh = &rcar_gen4_shift_data,
+	.rnc_field_width = 16,
+	.max_aflpn = 15,
+	.max_cftml = 31,
+	.postdiv = 2,
+	.shared_global_irqs = 0,
+	.multi_channel_irqs = 1,
+	.ch_interface_mode = 1,
+	.shared_can_regs = 1,
+	.external_clk = 1,
+	.fcan_pclk = 1,
+	.fixed_canfd = 1,
 };
 
 static const struct rcar_canfd_hw_info r9a09g047_hw_info = {
@@ -662,12 +686,13 @@ static const struct rcar_canfd_hw_info r9a09g047_hw_info = {
 	.rnc_field_width = 16,
 	.max_aflpn = 63,
 	.max_cftml = 31,
-	.max_channels = 6,
 	.postdiv = 1,
 	.multi_channel_irqs = 1,
 	.ch_interface_mode = 1,
 	.shared_can_regs = 1,
 	.external_clk = 0,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 static const struct rcar_canfd_hw_info r9a09g077_hw_info = {
@@ -679,12 +704,13 @@ static const struct rcar_canfd_hw_info r9a09g077_hw_info = {
 	.rnc_field_width = 16,
 	.max_aflpn = 15,
 	.max_cftml = 31,
-	.max_channels = 2,
 	.postdiv = 1,
 	.multi_channel_irqs = 1,
 	.ch_interface_mode = 1,
 	.shared_can_regs = 1,
 	.external_clk = 1,
+	.fcan_pclk = 0,
+	.fixed_canfd = 0,
 };
 
 /* Helper functions */
@@ -822,13 +848,13 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
 	}
 
 	/* Transition all Channels to reset mode */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_clear_bit(gpriv->base,
 				     RCANFD_CCTR(ch), RCANFD_CCTR_CSLPR);
 
 		rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch),
 				      RCANFD_CCTR_CHMDC_MASK,
-				      RCANFD_CCTR_CHDMC_CRESET);
+				      RCANFD_CCTR_CHMDC_CRESET);
 
 		/* Ensure Channel reset mode */
 		err = readl_poll_timeout((gpriv->base + RCANFD_CSTS(ch)), sts,
@@ -840,6 +866,9 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
 		}
 
 		/* Set the controller into appropriate mode */
+		if (gpriv->info->fixed_canfd)
+			continue;
+
 		if (gpriv->info->ch_interface_mode) {
 			/* Do not set CLOE and FDOE simultaneously */
 			if (!gpriv->fdmode) {
@@ -887,7 +916,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
 	rcar_canfd_set_bit(gpriv->base, RCANFD_GCFG, cfg);
 
 	/* Channel configuration settings */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_set_bit(gpriv->base, RCANFD_CCTR(ch),
 				   RCANFD_CCTR_ERRD);
 		rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch),
@@ -1258,7 +1287,7 @@ static irqreturn_t rcar_canfd_global_err_interrupt(int irq, void *dev_id)
 	struct rcar_canfd_global *gpriv = dev_id;
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels)
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
 		rcar_canfd_handle_global_err(gpriv, ch);
 
 	return IRQ_HANDLED;
@@ -1290,7 +1319,7 @@ static irqreturn_t rcar_canfd_global_receive_fifo_interrupt(int irq, void *dev_i
 	struct rcar_canfd_global *gpriv = dev_id;
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels)
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
 		rcar_canfd_handle_global_receive(gpriv, ch);
 
 	return IRQ_HANDLED;
@@ -1304,7 +1333,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
 	/* Global error interrupts still indicate a condition specific
 	 * to a channel. RxFIFO interrupt is a global interrupt.
 	 */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_handle_global_err(gpriv, ch);
 		rcar_canfd_handle_global_receive(gpriv, ch);
 	}
@@ -1400,7 +1429,7 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
 	u32 ch;
 
 	/* Common FIFO is a per channel resource */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_handle_channel_err(gpriv, ch);
 		rcar_canfd_handle_channel_tx(gpriv, ch);
 	}
@@ -1504,7 +1533,7 @@ static int rcar_canfd_start(struct net_device *ndev)
 
 	/* Set channel to Operational mode */
 	rcar_canfd_update_bit(priv->base, RCANFD_CCTR(ch),
-			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_COPM);
+			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHMDC_COPM);
 
 	/* Verify channel mode change */
 	err = readl_poll_timeout((priv->base + RCANFD_CSTS(ch)), sts,
@@ -1578,7 +1607,7 @@ static void rcar_canfd_stop(struct net_device *ndev)
 
 	/* Transition to channel reset mode  */
 	rcar_canfd_update_bit(priv->base, RCANFD_CCTR(ch),
-			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_CRESET);
+			      RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHMDC_CRESET);
 
 	/* Check Channel reset mode */
 	err = readl_poll_timeout((priv->base + RCANFD_CSTS(ch)), sts,
@@ -2037,7 +2066,7 @@ static int rcar_canfd_global_init(struct rcar_canfd_global *gpriv)
 	rcar_canfd_configure_controller(gpriv);
 
 	/* Configure per channel attributes */
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		/* Configure Channel's Rx fifo */
 		rcar_canfd_configure_rx(gpriv, ch);
 
@@ -2110,14 +2139,18 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	bool fdmode = true;			/* CAN FD only mode - default */
 	char name[9] = "channelX";
 	u32 ch, fcan_freq;
+	u8 max_channels;
 	int i;
 
 	info = of_device_get_match_data(dev);
+	max_channels = of_get_child_count(dev->of_node);
+	if (max_channels > RCANFD_NUM_CHANNELS)
+		return -EINVAL;
 
 	if (of_property_read_bool(dev->of_node, "renesas,no-can-fd"))
 		fdmode = false;			/* Classical CAN only mode */
 
-	for (i = 0; i < info->max_channels; ++i) {
+	for (i = 0; i < max_channels; ++i) {
 		name[7] = '0' + i;
 		of_child = of_get_available_child_by_name(dev->of_node, name);
 		if (of_child) {
@@ -2164,6 +2197,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	gpriv->pdev = pdev;
 	gpriv->channels_mask = channels_mask;
 	gpriv->fdmode = fdmode;
+	gpriv->max_channels = max_channels;
 	gpriv->info = info;
 
 	if (of_property_read_bool(dev->of_node, "renesas,fd-only"))
@@ -2190,13 +2224,20 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	 */
 	gpriv->can_clk = devm_clk_get(dev, "can_clk");
 	if (IS_ERR(gpriv->can_clk) || (clk_get_rate(gpriv->can_clk) == 0)) {
-		gpriv->can_clk = devm_clk_get(dev, "canfd");
-		if (IS_ERR(gpriv->can_clk))
-			return dev_err_probe(dev, PTR_ERR(gpriv->can_clk),
-					     "cannot get canfd clock\n");
+		if (info->fcan_pclk) {
+			fcan_freq = clk_get_rate(gpriv->clkp);
+			gpriv->can_clk = NULL;
+		} else {
+			gpriv->can_clk = devm_clk_get(dev, "canfd");
+			if (IS_ERR(gpriv->can_clk))
+				return dev_err_probe(dev, PTR_ERR(gpriv->can_clk),
+						     "cannot get canfd clock\n");
+
+			fcan_freq = clk_get_rate(gpriv->can_clk);
+		}
 
 		/* CANFD clock may be further divided within the IP */
-		fcan_freq = clk_get_rate(gpriv->can_clk) / info->postdiv;
+		fcan_freq /= info->postdiv;
 	} else {
 		fcan_freq = clk_get_rate(gpriv->can_clk);
 		gpriv->extclk = gpriv->info->external_clk;
@@ -2258,7 +2299,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	if (err)
 		goto fail_mode;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		err = rcar_canfd_channel_probe(gpriv, ch, fcan_freq,
 					       transceivers[ch]);
 		if (err)
@@ -2272,7 +2313,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	return 0;
 
 fail_channel:
-	for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels)
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
 		rcar_canfd_channel_remove(gpriv, ch);
 fail_mode:
 	rcar_canfd_global_deinit(gpriv, false);
@@ -2285,7 +2326,7 @@ static void rcar_canfd_remove(struct platform_device *pdev)
 	struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev);
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		rcar_canfd_disable_channel_interrupts(gpriv->ch[ch]);
 		rcar_canfd_channel_remove(gpriv, ch);
 	}
@@ -2299,7 +2340,7 @@ static int rcar_canfd_suspend(struct device *dev)
 	int err;
 	u32 ch;
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		struct rcar_canfd_channel *priv = gpriv->ch[ch];
 		struct net_device *ndev = priv->ndev;
 
@@ -2336,7 +2377,7 @@ static int rcar_canfd_resume(struct device *dev)
 		return err;
 	}
 
-	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+	for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) {
 		struct rcar_canfd_channel *priv = gpriv->ch[ch];
 		struct net_device *ndev = priv->ndev;
 
@@ -2361,6 +2402,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,
 
 static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {
 	{ .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info },
+	{ .compatible = "renesas,r9a08g045-canfd", .data = &r9a08g045_hw_info },
+	{ .compatible = "renesas,r9a08g046-canfd", .data = &r9a08g045_hw_info },
 	{ .compatible = "renesas,r9a09g047-canfd", .data = &r9a09g047_hw_info },
 	{ .compatible = "renesas,r9a09g077-canfd", .data = &r9a09g077_hw_info },
 	{ .compatible = "renesas,rcar-gen3-canfd", .data = &rcar_gen3_hw_info },
diff --git a/drivers/net/can/softing/Kconfig b/drivers/net/can/softing/Kconfig
deleted file mode 100644
index 8afd7d0a1000a..0000000000000
--- a/drivers/net/can/softing/Kconfig
+++ /dev/null
@@ -1,31 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config CAN_SOFTING
-	tristate "Softing Gmbh CAN generic support"
-	depends on HAS_IOMEM
-	help
-	  Support for CAN cards from Softing Gmbh & some cards
-	  from Vector Gmbh.
-	  Softing Gmbh CAN cards come with 1 or 2 physical buses.
-	  Those cards typically use Dual Port RAM to communicate
-	  with the host CPU. The interface is then identical for PCI
-	  and PCMCIA cards. This driver operates on a platform device,
-	  which has been created by softing_cs or softing_pci driver.
-	  Warning:
-	  The API of the card does not allow fine control per bus, but
-	  controls the 2 buses on the card together.
-	  As such, some actions (start/stop/busoff recovery) on 1 bus
-	  must bring down the other bus too temporarily.
-
-config CAN_SOFTING_CS
-	tristate "Softing Gmbh CAN pcmcia cards"
-	depends on PCMCIA
-	depends on CAN_SOFTING
-	help
-	  Support for PCMCIA cards from Softing Gmbh & some cards
-	  from Vector Gmbh.
-	  You need firmware for these, which you can get at
-	  https://github.com/linux-can/can-firmware
-	  This version of the driver is written against
-	  firmware version 4.6 (softing-fw-4.6-binaries.tar.gz)
-	  In order to use the card as CAN device, you need the Softing generic
-	  support too.
diff --git a/drivers/net/can/softing/Makefile b/drivers/net/can/softing/Makefile
deleted file mode 100644
index c511540003779..0000000000000
--- a/drivers/net/can/softing/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-softing-y := softing_main.o softing_fw.o
-obj-$(CONFIG_CAN_SOFTING) += softing.o
-obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o
diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h
deleted file mode 100644
index 2893007ea05e1..0000000000000
--- a/drivers/net/can/softing/softing.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * softing common interfaces
- *
- * by Kurt Van Dijck, 2008-2010
- */
-
-#include <linux/atomic.h>
-#include <linux/netdevice.h>
-#include <linux/ktime.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/can.h>
-#include <linux/can/dev.h>
-
-#include "softing_platform.h"
-
-struct softing;
-
-struct softing_priv {
-	struct can_priv can; /* must be the first member! */
-	struct net_device *netdev;
-	struct softing *card;
-	struct {
-		int pending;
-		/* variables which hold the circular buffer */
-		int echo_put;
-		int echo_get;
-	} tx;
-	struct can_bittiming_const btr_const;
-	int index;
-	uint8_t output;
-	uint16_t chip;
-};
-#define netdev2softing(netdev)	((struct softing_priv *)netdev_priv(netdev))
-
-struct softing {
-	const struct softing_platform_data *pdat;
-	struct platform_device *pdev;
-	struct net_device *net[2];
-	spinlock_t spin; /* protect this structure & DPRAM access */
-	ktime_t ts_ref;
-	ktime_t ts_overflow; /* timestamp overflow value, in ktime */
-
-	struct {
-		/* indication of firmware status */
-		int up;
-		/* protection of the 'up' variable */
-		struct mutex lock;
-	} fw;
-	struct {
-		int nr;
-		int requested;
-		int svc_count;
-		unsigned int dpram_position;
-	} irq;
-	struct {
-		int pending;
-		int last_bus;
-		/*
-		 * keep the bus that last tx'd a message,
-		 * in order to let every netdev queue resume
-		 */
-	} tx;
-	__iomem uint8_t *dpram;
-	unsigned long dpram_phys;
-	unsigned long dpram_size;
-	struct {
-		uint16_t fw_version, hw_version, license, serial;
-		uint16_t chip[2];
-		unsigned int freq; /* remote cpu's operating frequency */
-	} id;
-};
-
-int softing_default_output(struct net_device *netdev);
-
-ktime_t softing_raw2ktime(struct softing *card, u32 raw);
-
-int softing_chip_poweron(struct softing *card);
-
-int softing_bootloader_command(struct softing *card, int16_t cmd,
-			       const char *msg);
-
-/* Load firmware after reset */
-int softing_load_fw(const char *file, struct softing *card,
-		    __iomem uint8_t *virt, unsigned int size, int offset);
-
-/* Load final application firmware after bootloader */
-int softing_load_app_fw(const char *file, struct softing *card);
-
-/*
- * enable or disable irq
- * only called with fw.lock locked
- */
-int softing_enable_irq(struct softing *card, int enable);
-
-/* start/stop 1 bus on card */
-int softing_startstop(struct net_device *netdev, int up);
-
-/* netif_rx() */
-int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
-		      ktime_t ktime);
-
-/* SOFTING DPRAM mappings */
-#define DPRAM_RX		0x0000
-	#define DPRAM_RX_SIZE	32
-	#define DPRAM_RX_CNT	16
-#define DPRAM_RX_RD		0x0201	/* uint8_t */
-#define DPRAM_RX_WR		0x0205	/* uint8_t */
-#define DPRAM_RX_LOST		0x0207	/* uint8_t */
-
-#define DPRAM_FCT_PARAM		0x0300	/* int16_t [20] */
-#define DPRAM_FCT_RESULT	0x0328	/* int16_t */
-#define DPRAM_FCT_HOST		0x032b	/* uint16_t */
-
-#define DPRAM_INFO_BUSSTATE	0x0331	/* uint16_t */
-#define DPRAM_INFO_BUSSTATE2	0x0335	/* uint16_t */
-#define DPRAM_INFO_ERRSTATE	0x0339	/* uint16_t */
-#define DPRAM_INFO_ERRSTATE2	0x033d	/* uint16_t */
-#define DPRAM_RESET		0x0341	/* uint16_t */
-#define DPRAM_CLR_RECV_FIFO	0x0345	/* uint16_t */
-#define DPRAM_RESET_TIME	0x034d	/* uint16_t */
-#define DPRAM_TIME		0x0350	/* uint64_t */
-#define DPRAM_WR_START		0x0358	/* uint8_t */
-#define DPRAM_WR_END		0x0359	/* uint8_t */
-#define DPRAM_RESET_RX_FIFO	0x0361	/* uint16_t */
-#define DPRAM_RESET_TX_FIFO	0x0364	/* uint8_t */
-#define DPRAM_READ_FIFO_LEVEL	0x0365	/* uint8_t */
-#define DPRAM_RX_FIFO_LEVEL	0x0366	/* uint16_t */
-#define DPRAM_TX_FIFO_LEVEL	0x0366	/* uint16_t */
-
-#define DPRAM_TX		0x0400	/* uint16_t */
-	#define DPRAM_TX_SIZE	16
-	#define DPRAM_TX_CNT	32
-#define DPRAM_TX_RD		0x0601	/* uint8_t */
-#define DPRAM_TX_WR		0x0605	/* uint8_t */
-
-#define DPRAM_COMMAND		0x07e0	/* uint16_t */
-#define DPRAM_RECEIPT		0x07f0	/* uint16_t */
-#define DPRAM_IRQ_TOHOST	0x07fe	/* uint8_t */
-#define DPRAM_IRQ_TOCARD	0x07ff	/* uint8_t */
-
-#define DPRAM_V2_RESET		0x0e00	/* uint8_t */
-#define DPRAM_V2_IRQ_TOHOST	0x0e02	/* uint8_t */
-
-#define TXMAX	(DPRAM_TX_CNT - 1)
-
-/* DPRAM return codes */
-#define RES_NONE	0
-#define RES_OK		1
-#define RES_NOK		2
-#define RES_UNKNOWN	3
-/* DPRAM flags */
-#define CMD_TX		0x01
-#define CMD_ACK		0x02
-#define CMD_XTD		0x04
-#define CMD_RTR		0x08
-#define CMD_ERR		0x10
-#define CMD_BUS2	0x80
-
-/* returned fifo entry bus state masks */
-#define SF_MASK_BUSOFF		0x80
-#define SF_MASK_EPASSIVE	0x60
-
-/* bus states */
-#define STATE_BUSOFF	2
-#define STATE_EPASSIVE	1
-#define STATE_EACTIVE	0
diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c
deleted file mode 100644
index 3cea14cf055ad..0000000000000
--- a/drivers/net/can/softing/softing_cs.c
+++ /dev/null
@@ -1,335 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010
- *
- * - Kurt Van Dijck, EIA Electronics
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include "softing_platform.h"
-
-static int softingcs_index;
-static DEFINE_SPINLOCK(softingcs_index_lock);
-
-static int softingcs_reset(struct platform_device *pdev, int v);
-static int softingcs_enable_irq(struct platform_device *pdev, int v);
-
-/*
- * platform_data descriptions
- */
-#define MHZ (1000*1000)
-static const struct softing_platform_data softingcs_platform_data[] = {
-{
-	.name = "CANcard",
-	.manf = 0x0168, .prod = 0x001,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "CANcard-NEC",
-	.manf = 0x0168, .prod = 0x002,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "CANcard-SJA",
-	.manf = 0x0168, .prod = 0x004,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "CANcard-2",
-	.manf = 0x0168, .prod = 0x005,
-	.generation = 2,
-	.nbus = 2,
-	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x1000,
-	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = NULL,
-}, {
-	.name = "Vector-CANcard",
-	.manf = 0x0168, .prod = 0x081,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "Vector-CANcard-SJA",
-	.manf = 0x0168, .prod = 0x084,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cansja.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "Vector-CANcard-2",
-	.manf = 0x0168, .prod = 0x085,
-	.generation = 2,
-	.nbus = 2,
-	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x1000,
-	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = NULL,
-}, {
-	.name = "EDICcard-NEC",
-	.manf = 0x0168, .prod = 0x102,
-	.generation = 1,
-	.nbus = 2,
-	.freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x0800,
-	.boot = {0x0000, 0x000000, fw_dir "bcard.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancard.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = softingcs_enable_irq,
-}, {
-	.name = "EDICcard-2",
-	.manf = 0x0168, .prod = 0x105,
-	.generation = 2,
-	.nbus = 2,
-	.freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4,
-	.dpram_size = 0x1000,
-	.boot = {0x0000, 0x000000, fw_dir "bcard2.bin",},
-	.load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",},
-	.app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",},
-	.reset = softingcs_reset,
-	.enable_irq = NULL,
-}, {
-	0, 0,
-},
-};
-
-MODULE_FIRMWARE(fw_dir "bcard.bin");
-MODULE_FIRMWARE(fw_dir "ldcard.bin");
-MODULE_FIRMWARE(fw_dir "cancard.bin");
-MODULE_FIRMWARE(fw_dir "cansja.bin");
-
-MODULE_FIRMWARE(fw_dir "bcard2.bin");
-MODULE_FIRMWARE(fw_dir "ldcard2.bin");
-MODULE_FIRMWARE(fw_dir "cancrd2.bin");
-
-static const struct softing_platform_data
-*softingcs_find_platform_data(unsigned int manf, unsigned int prod)
-{
-	const struct softing_platform_data *lp;
-
-	for (lp = softingcs_platform_data; lp->manf; ++lp) {
-		if ((lp->manf == manf) && (lp->prod == prod))
-			return lp;
-	}
-	return NULL;
-}
-
-/*
- * platformdata callbacks
- */
-static int softingcs_reset(struct platform_device *pdev, int v)
-{
-	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
-
-	dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20);
-	return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20);
-}
-
-static int softingcs_enable_irq(struct platform_device *pdev, int v)
-{
-	struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent);
-
-	dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0);
-	return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0);
-}
-
-/*
- * pcmcia check
- */
-static int softingcs_probe_config(struct pcmcia_device *pcmcia, void *priv_data)
-{
-	struct softing_platform_data *pdat = priv_data;
-	struct resource *pres;
-	int memspeed = 0;
-
-	WARN_ON(!pdat);
-	pres = pcmcia->resource[PCMCIA_IOMEM_0];
-	if (resource_size(pres) < 0x1000)
-		return -ERANGE;
-
-	pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	if (pdat->generation < 2) {
-		pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8;
-		memspeed = 3;
-	} else {
-		pres->flags |= WIN_DATA_WIDTH_16;
-	}
-	return pcmcia_request_window(pcmcia, pres, memspeed);
-}
-
-static void softingcs_remove(struct pcmcia_device *pcmcia)
-{
-	struct platform_device *pdev = pcmcia->priv;
-
-	/* free bits */
-	platform_device_unregister(pdev);
-	/* release pcmcia stuff */
-	pcmcia_disable_device(pcmcia);
-}
-
-/*
- * platform_device wrapper
- * pdev->resource has 2 entries: io & irq
- */
-static void softingcs_pdev_release(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	kfree(pdev);
-}
-
-static int softingcs_probe(struct pcmcia_device *pcmcia)
-{
-	int ret;
-	struct platform_device *pdev;
-	const struct softing_platform_data *pdat;
-	struct resource *pres;
-	struct dev {
-		struct platform_device pdev;
-		struct resource res[2];
-	} *dev;
-
-	/* find matching platform_data */
-	pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id);
-	if (!pdat)
-		return -ENOTTY;
-
-	/* setup pcmcia device */
-	pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM |
-		CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
-	ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat);
-	if (ret)
-		goto pcmcia_failed;
-
-	ret = pcmcia_enable_device(pcmcia);
-	if (ret < 0)
-		goto pcmcia_failed;
-
-	pres = pcmcia->resource[PCMCIA_IOMEM_0];
-	if (!pres) {
-		ret = -EBADF;
-		goto pcmcia_bad;
-	}
-
-	/* create softing platform device */
-	dev = kzalloc_obj(*dev);
-	if (!dev) {
-		ret = -ENOMEM;
-		goto mem_failed;
-	}
-	dev->pdev.resource = dev->res;
-	dev->pdev.num_resources = ARRAY_SIZE(dev->res);
-	dev->pdev.dev.release = softingcs_pdev_release;
-
-	pdev = &dev->pdev;
-	pdev->dev.platform_data = (void *)pdat;
-	pdev->dev.parent = &pcmcia->dev;
-	pcmcia->priv = pdev;
-
-	/* platform device resources */
-	pdev->resource[0].flags = IORESOURCE_MEM;
-	pdev->resource[0].start = pres->start;
-	pdev->resource[0].end = pres->end;
-
-	pdev->resource[1].flags = IORESOURCE_IRQ;
-	pdev->resource[1].start = pcmcia->irq;
-	pdev->resource[1].end = pdev->resource[1].start;
-
-	/* platform device setup */
-	spin_lock(&softingcs_index_lock);
-	pdev->id = softingcs_index++;
-	spin_unlock(&softingcs_index_lock);
-	pdev->name = "softing";
-	dev_set_name(&pdev->dev, "softingcs.%i", pdev->id);
-	ret = platform_device_register(pdev);
-	if (ret < 0)
-		goto platform_failed;
-
-	dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev));
-	return 0;
-
-platform_failed:
-	platform_device_put(pdev);
-mem_failed:
-pcmcia_bad:
-pcmcia_failed:
-	pcmcia_disable_device(pcmcia);
-	pcmcia->priv = NULL;
-	return ret;
-}
-
-static const struct pcmcia_device_id softingcs_ids[] = {
-	/* softing */
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005),
-	/* vector, manufacturer? */
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085),
-	/* EDIC */
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102),
-	PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105),
-	PCMCIA_DEVICE_NULL,
-};
-
-MODULE_DEVICE_TABLE(pcmcia, softingcs_ids);
-
-static struct pcmcia_driver softingcs_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "softingcs",
-	.id_table	= softingcs_ids,
-	.probe		= softingcs_probe,
-	.remove		= softingcs_remove,
-};
-
-module_pcmcia_driver(softingcs_driver);
-
-MODULE_DESCRIPTION("softing CANcard driver"
-		", links PCMCIA card to softing driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
deleted file mode 100644
index 282570daf3efe..0000000000000
--- a/drivers/net/can/softing/softing_fw.c
+++ /dev/null
@@ -1,700 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010
- *
- * - Kurt Van Dijck, EIA Electronics
- */
-
-#include <linux/firmware.h>
-#include <linux/sched/signal.h>
-#include <asm/div64.h>
-#include <asm/io.h>
-
-#include "softing.h"
-
-/*
- * low level DPRAM command.
- * Make sure that card->dpram[DPRAM_FCT_HOST] is preset
- */
-static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector,
-		const char *msg)
-{
-	int ret;
-	unsigned long stamp;
-
-	iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]);
-	iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]);
-	iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]);
-	/* be sure to flush this to the card */
-	wmb();
-	stamp = jiffies + 1 * HZ;
-	/* wait for card */
-	do {
-		/* DPRAM_FCT_HOST is _not_ aligned */
-		ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) +
-			(ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8);
-		/* don't have any cached variables */
-		rmb();
-		if (ret == RES_OK)
-			/* read return-value now */
-			return ioread16(&card->dpram[DPRAM_FCT_RESULT]);
-
-		if ((ret != vector) || time_after(jiffies, stamp))
-			break;
-		/* process context => relax */
-		usleep_range(500, 10000);
-	} while (1);
-
-	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
-	dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret);
-	return ret;
-}
-
-static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg)
-{
-	int ret;
-
-	ret = _softing_fct_cmd(card, cmd, 0, msg);
-	if (ret > 0) {
-		dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret);
-		ret = -EIO;
-	}
-	return ret;
-}
-
-int softing_bootloader_command(struct softing *card, int16_t cmd,
-		const char *msg)
-{
-	int ret;
-	unsigned long stamp;
-
-	iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]);
-	iowrite16(cmd, &card->dpram[DPRAM_COMMAND]);
-	/* be sure to flush this to the card */
-	wmb();
-	stamp = jiffies + 3 * HZ;
-	/* wait for card */
-	do {
-		ret = ioread16(&card->dpram[DPRAM_RECEIPT]);
-		/* don't have any cached variables */
-		rmb();
-		if (ret == RES_OK)
-			return 0;
-		if (time_after(jiffies, stamp))
-			break;
-		/* process context => relax */
-		usleep_range(500, 10000);
-	} while (!signal_pending(current));
-
-	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;
-	dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret);
-	return ret;
-}
-
-static int fw_parse(const u8 **pmem, const u8 *limit, u16 *ptype,
-		    u32 *paddr, u16 *plen, const u8 **pdat)
-{
-	uint16_t checksum[2];
-	const u8 *mem;
-	const u8 *record_end;
-
-	/*
-	 * firmware records are a binary, unaligned stream composed of:
-	 * uint16_t type;
-	 * uint32_t addr;
-	 * uint16_t len;
-	 * uint8_t dat[len];
-	 * uint16_t checksum;
-	 * all values in little endian.
-	 * We could define a struct for this, with __attribute__((packed)),
-	 * but would that solve the alignment in _all_ cases (cfr. the
-	 * struct itself may be an odd address)?
-	 *
-	 * I chose to use leXX_to_cpup() since this solves both
-	 * endianness & alignment.
-	 */
-	mem = *pmem;
-	/* A record needs an 8-byte prefix and a 2-byte checksum. */
-	if (mem > limit || limit - mem < 10)
-		return -EINVAL;
-
-	*ptype = le16_to_cpup((void *)&mem[0]);
-	*paddr = le32_to_cpup((void *)&mem[2]);
-	*plen = le16_to_cpup((void *)&mem[6]);
-	if (*plen > limit - mem - 10)
-		return -EINVAL;
-
-	*pdat = &mem[8];
-	/* verify checksum */
-	record_end = &mem[8 + *plen];
-	checksum[0] = le16_to_cpup((void *)record_end);
-	for (checksum[1] = 0; mem < record_end; ++mem)
-		checksum[1] += *mem;
-	if (checksum[0] != checksum[1])
-		return -EINVAL;
-	/* increment */
-	*pmem += 10 + *plen;
-	return 0;
-}
-
-int softing_load_fw(const char *file, struct softing *card,
-		__iomem uint8_t *dpram, unsigned int size, int offset)
-{
-	const struct firmware *fw;
-	int ret;
-	const uint8_t *mem, *end, *dat;
-	uint16_t type, len;
-	uint32_t addr;
-	uint8_t *buf = NULL, *new_buf;
-	s64 dpram_offset;
-	int buflen = 0;
-	int8_t type_end = 0;
-
-	ret = request_firmware(&fw, file, &card->pdev->dev);
-	if (ret < 0)
-		return ret;
-	dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes"
-		", offset %c0x%04x\n",
-		card->pdat->name, file, (unsigned int)fw->size,
-		(offset >= 0) ? '+' : '-', (unsigned int)abs(offset));
-	/* parse the firmware */
-	mem = fw->data;
-	end = &mem[fw->size];
-	/* look for header record */
-	ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-	if (ret < 0)
-		goto failed;
-	if (type != 0xffff)
-		goto failed;
-	if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) {
-		ret = -EINVAL;
-		goto failed;
-	}
-	/* ok, we had a header */
-	while (mem < end) {
-		ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-		if (ret < 0)
-			goto failed;
-		if (type == 3) {
-			/* start address, not used here */
-			continue;
-		} else if (type == 1) {
-			/* eof */
-			type_end = 1;
-			break;
-		} else if (type != 0) {
-			ret = -EINVAL;
-			goto failed;
-		}
-
-		dpram_offset = (s64)addr + offset;
-		if (dpram_offset < 0 || dpram_offset > size ||
-		    len > size - dpram_offset) {
-			ret = -EINVAL;
-			goto failed;
-		}
-		memcpy_toio(&dpram[dpram_offset], dat, len);
-		/* be sure to flush caches from IO space */
-		mb();
-		if (len > buflen) {
-			/* align buflen */
-			buflen = (len + (1024-1)) & ~(1024-1);
-			new_buf = krealloc(buf, buflen, GFP_KERNEL);
-			if (!new_buf) {
-				ret = -ENOMEM;
-				goto failed;
-			}
-			buf = new_buf;
-		}
-		/* verify record data */
-		memcpy_fromio(buf, &dpram[dpram_offset], len);
-		if (memcmp(buf, dat, len)) {
-			/* is not ok */
-			dev_alert(&card->pdev->dev, "DPRAM readback failed\n");
-			ret = -EIO;
-			goto failed;
-		}
-	}
-	if (!type_end)
-		/* no end record seen */
-		goto failed;
-	ret = 0;
-failed:
-	kfree(buf);
-	release_firmware(fw);
-	if (ret < 0)
-		dev_info(&card->pdev->dev, "firmware %s failed\n", file);
-	return ret;
-}
-
-int softing_load_app_fw(const char *file, struct softing *card)
-{
-	const struct firmware *fw;
-	const uint8_t *mem, *end, *dat;
-	int ret, j;
-	uint16_t type, len;
-	uint32_t addr, start_addr = 0;
-	unsigned int sum, rx_sum;
-	int8_t type_end = 0, type_entrypoint = 0;
-
-	ret = request_firmware(&fw, file, &card->pdev->dev);
-	if (ret) {
-		dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n",
-			file, ret);
-		return ret;
-	}
-	dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n",
-		file, (unsigned long)fw->size);
-	/* parse the firmware */
-	mem = fw->data;
-	end = &mem[fw->size];
-	/* look for header record */
-	ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-	if (ret)
-		goto failed;
-	ret = -EINVAL;
-	if (type != 0xffff) {
-		dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n",
-			type);
-		goto failed;
-	}
-	if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) {
-		dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n",
-				len, dat);
-		goto failed;
-	}
-	/* ok, we had a header */
-	while (mem < end) {
-		ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
-		if (ret)
-			goto failed;
-
-		if (type == 3) {
-			/* start address */
-			start_addr = addr;
-			type_entrypoint = 1;
-			continue;
-		} else if (type == 1) {
-			/* eof */
-			type_end = 1;
-			break;
-		} else if (type != 0) {
-			dev_alert(&card->pdev->dev,
-					"unknown record type 0x%04x\n", type);
-			ret = -EINVAL;
-			goto failed;
-		}
-
-		/* regular data */
-		for (sum = 0, j = 0; j < len; ++j)
-			sum += dat[j];
-		/* work in 16bit (target) */
-		sum &= 0xffff;
-
-		if (card->pdat->app.offs > card->dpram_size ||
-		    len > card->dpram_size - card->pdat->app.offs) {
-			ret = -EINVAL;
-			goto failed;
-		}
-
-		memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len);
-		iowrite32(card->pdat->app.offs + card->pdat->app.addr,
-				&card->dpram[DPRAM_COMMAND + 2]);
-		iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]);
-		iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]);
-		iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]);
-		ret = softing_bootloader_command(card, 1, "loading app.");
-		if (ret < 0)
-			goto failed;
-		/* verify checksum */
-		rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]);
-		if (rx_sum != sum) {
-			dev_alert(&card->pdev->dev, "SRAM seems to be damaged"
-				", wanted 0x%04x, got 0x%04x\n", sum, rx_sum);
-			ret = -EIO;
-			goto failed;
-		}
-	}
-	if (!type_end || !type_entrypoint)
-		goto failed;
-	/* start application in card */
-	iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]);
-	iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]);
-	ret = softing_bootloader_command(card, 3, "start app.");
-	if (ret < 0)
-		goto failed;
-	ret = 0;
-failed:
-	release_firmware(fw);
-	if (ret < 0)
-		dev_info(&card->pdev->dev, "firmware %s failed\n", file);
-	return ret;
-}
-
-static int softing_reset_chip(struct softing *card)
-{
-	int ret;
-
-	do {
-		/* reset chip */
-		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]);
-		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]);
-		iowrite8(1, &card->dpram[DPRAM_RESET]);
-		iowrite8(0, &card->dpram[DPRAM_RESET+1]);
-
-		ret = softing_fct_cmd(card, 0, "reset_can");
-		if (!ret)
-			break;
-		if (signal_pending(current))
-			/* don't wait any longer */
-			break;
-	} while (1);
-	card->tx.pending = 0;
-	return ret;
-}
-
-int softing_chip_poweron(struct softing *card)
-{
-	int ret;
-	/* sync */
-	ret = _softing_fct_cmd(card, 99, 0x55, "sync-a");
-	if (ret < 0)
-		goto failed;
-
-	ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b");
-	if (ret < 0)
-		goto failed;
-
-	ret = softing_reset_chip(card);
-	if (ret < 0)
-		goto failed;
-	/* get_serial */
-	ret = softing_fct_cmd(card, 43, "get_serial_number");
-	if (ret < 0)
-		goto failed;
-	card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]);
-	/* get_version */
-	ret = softing_fct_cmd(card, 12, "get_version");
-	if (ret < 0)
-		goto failed;
-	card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]);
-	card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]);
-	card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]);
-	card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]);
-	card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]);
-	return 0;
-failed:
-	return ret;
-}
-
-static void softing_initialize_timestamp(struct softing *card)
-{
-	uint64_t ovf;
-
-	card->ts_ref = ktime_get();
-
-	/* 16MHz is the reference */
-	ovf = 0x100000000ULL * 16;
-	do_div(ovf, card->pdat->freq ?: 16);
-
-	card->ts_overflow = ktime_add_us(0, ovf);
-}
-
-ktime_t softing_raw2ktime(struct softing *card, u32 raw)
-{
-	uint64_t rawl;
-	ktime_t now, real_offset;
-	ktime_t target;
-	ktime_t tmp;
-
-	now = ktime_get();
-	real_offset = ktime_sub(ktime_get_real(), now);
-
-	/* find nsec from card */
-	rawl = raw * 16;
-	do_div(rawl, card->pdat->freq ?: 16);
-	target = ktime_add_us(card->ts_ref, rawl);
-	/* test for overflows */
-	tmp = ktime_add(target, card->ts_overflow);
-	while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) {
-		card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow);
-		target = tmp;
-		tmp = ktime_add(target, card->ts_overflow);
-	}
-	return ktime_add(target, real_offset);
-}
-
-static inline int softing_error_reporting(struct net_device *netdev)
-{
-	struct softing_priv *priv = netdev_priv(netdev);
-
-	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
-		? 1 : 0;
-}
-
-int softing_startstop(struct net_device *dev, int up)
-{
-	int ret;
-	struct softing *card;
-	struct softing_priv *priv;
-	struct net_device *netdev;
-	int bus_bitmask_start;
-	int j, error_reporting;
-	struct can_frame msg;
-	const struct can_bittiming *bt;
-
-	priv = netdev_priv(dev);
-	card = priv->card;
-
-	if (!card->fw.up)
-		return -EIO;
-
-	ret = mutex_lock_interruptible(&card->fw.lock);
-	if (ret)
-		return ret;
-
-	bus_bitmask_start = 0;
-	if (up)
-		/* prepare to start this bus as well */
-		bus_bitmask_start |= (1 << priv->index);
-	/* bring netdevs down */
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		netdev = card->net[j];
-		if (!netdev)
-			continue;
-		priv = netdev_priv(netdev);
-
-		if (dev != netdev)
-			netif_stop_queue(netdev);
-
-		if (netif_running(netdev)) {
-			if (dev != netdev)
-				bus_bitmask_start |= (1 << j);
-			priv->tx.pending = 0;
-			priv->tx.echo_put = 0;
-			priv->tx.echo_get = 0;
-			/*
-			 * this bus' may just have called open_candev()
-			 * which is rather stupid to call close_candev()
-			 * already
-			 * but we may come here from busoff recovery too
-			 * in which case the echo_skb _needs_ flushing too.
-			 * just be sure to call open_candev() again
-			 */
-			close_candev(netdev);
-		}
-		priv->can.state = CAN_STATE_STOPPED;
-	}
-	card->tx.pending = 0;
-
-	softing_enable_irq(card, 0);
-	ret = softing_reset_chip(card);
-	if (ret)
-		goto failed;
-	if (!bus_bitmask_start)
-		/* no buses to be brought up */
-		goto card_done;
-
-	if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2)
-			&& (softing_error_reporting(card->net[0])
-				!= softing_error_reporting(card->net[1]))) {
-		dev_alert(&card->pdev->dev,
-				"err_reporting flag differs for buses\n");
-		goto invalid;
-	}
-	error_reporting = 0;
-	if (bus_bitmask_start & 1) {
-		netdev = card->net[0];
-		priv = netdev_priv(netdev);
-		error_reporting += softing_error_reporting(netdev);
-		/* init chip 1 */
-		bt = &priv->can.bittiming;
-		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		iowrite16(bt->phase_seg1 + bt->prop_seg,
-				&card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
-				&card->dpram[DPRAM_FCT_PARAM + 10]);
-		ret = softing_fct_cmd(card, 1, "initialize_chip[0]");
-		if (ret < 0)
-			goto failed;
-		/* set mode */
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		ret = softing_fct_cmd(card, 3, "set_mode[0]");
-		if (ret < 0)
-			goto failed;
-		/* set filter */
-		/* 11bit id & mask */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		/* 29bit id.lo & mask.lo & id.hi & mask.hi */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
-		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
-		ret = softing_fct_cmd(card, 7, "set_filter[0]");
-		if (ret < 0)
-			goto failed;
-		/* set output control */
-		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		ret = softing_fct_cmd(card, 5, "set_output[0]");
-		if (ret < 0)
-			goto failed;
-	}
-	if (bus_bitmask_start & 2) {
-		netdev = card->net[1];
-		priv = netdev_priv(netdev);
-		error_reporting += softing_error_reporting(netdev);
-		/* init chip2 */
-		bt = &priv->can.bittiming;
-		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		iowrite16(bt->phase_seg1 + bt->prop_seg,
-				&card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,
-				&card->dpram[DPRAM_FCT_PARAM + 10]);
-		ret = softing_fct_cmd(card, 2, "initialize_chip[1]");
-		if (ret < 0)
-			goto failed;
-		/* set mode2 */
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		ret = softing_fct_cmd(card, 4, "set_mode[1]");
-		if (ret < 0)
-			goto failed;
-		/* set filter2 */
-		/* 11bit id & mask */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);
-		/* 29bit id.lo & mask.lo & id.hi & mask.hi */
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);
-		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);
-		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);
-		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);
-		ret = softing_fct_cmd(card, 8, "set_filter[1]");
-		if (ret < 0)
-			goto failed;
-		/* set output control2 */
-		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);
-		ret = softing_fct_cmd(card, 6, "set_output[1]");
-		if (ret < 0)
-			goto failed;
-	}
-
-	/* enable_error_frame
-	 *
-	 * Error reporting is switched off at the moment since
-	 * the receiving of them is not yet 100% verified
-	 * This should be enabled sooner or later
-	 */
-	if (0 && error_reporting) {
-		ret = softing_fct_cmd(card, 51, "enable_error_frame");
-		if (ret < 0)
-			goto failed;
-	}
-
-	/* initialize interface */
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]);
-	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]);
-	ret = softing_fct_cmd(card, 17, "initialize_interface");
-	if (ret < 0)
-		goto failed;
-	/* enable_fifo */
-	ret = softing_fct_cmd(card, 36, "enable_fifo");
-	if (ret < 0)
-		goto failed;
-	/* enable fifo tx ack */
-	ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]");
-	if (ret < 0)
-		goto failed;
-	/* enable fifo tx ack2 */
-	ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]");
-	if (ret < 0)
-		goto failed;
-	/* start_chip */
-	ret = softing_fct_cmd(card, 11, "start_chip");
-	if (ret < 0)
-		goto failed;
-	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]);
-	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]);
-	if (card->pdat->generation < 2) {
-		iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
-		/* flush the DPRAM caches */
-		wmb();
-	}
-
-	softing_initialize_timestamp(card);
-
-	/*
-	 * do socketcan notifications/status changes
-	 * from here, no errors should occur, or the failed: part
-	 * must be reviewed
-	 */
-	memset(&msg, 0, sizeof(msg));
-	msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
-	msg.len = CAN_ERR_DLC;
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (!(bus_bitmask_start & (1 << j)))
-			continue;
-		netdev = card->net[j];
-		if (!netdev)
-			continue;
-		priv = netdev_priv(netdev);
-		priv->can.state = CAN_STATE_ERROR_ACTIVE;
-		open_candev(netdev);
-		if (dev != netdev) {
-			/* notify other buses on the restart */
-			softing_netdev_rx(netdev, &msg, 0);
-			++priv->can.can_stats.restarts;
-		}
-		netif_wake_queue(netdev);
-	}
-
-	/* enable interrupts */
-	ret = softing_enable_irq(card, 1);
-	if (ret)
-		goto failed;
-card_done:
-	mutex_unlock(&card->fw.lock);
-	return 0;
-invalid:
-	ret = -EINVAL;
-failed:
-	softing_enable_irq(card, 0);
-	softing_reset_chip(card);
-	mutex_unlock(&card->fw.lock);
-	/* bring all other interfaces down */
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		netdev = card->net[j];
-		if (!netdev)
-			continue;
-		dev_close(netdev);
-	}
-	return ret;
-}
-
-int softing_default_output(struct net_device *netdev)
-{
-	struct softing_priv *priv = netdev_priv(netdev);
-	struct softing *card = priv->card;
-
-	switch (priv->chip) {
-	case 1000:
-		return (card->pdat->generation < 2) ? 0xfb : 0xfa;
-	case 5:
-		return 0x60;
-	default:
-		return 0x40;
-	}
-}
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
deleted file mode 100644
index 519ab3097f866..0000000000000
--- a/drivers/net/can/softing/softing_main.c
+++ /dev/null
@@ -1,864 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2008-2010
- *
- * - Kurt Van Dijck, EIA Electronics
- */
-
-#include <linux/ethtool.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "softing.h"
-
-#define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1)
-
-/*
- * test is a specific CAN netdev
- * is online (ie. up 'n running, not sleeping, not busoff
- */
-static inline int canif_is_active(struct net_device *netdev)
-{
-	struct can_priv *can = netdev_priv(netdev);
-
-	if (!netif_running(netdev))
-		return 0;
-	return (can->state <= CAN_STATE_ERROR_PASSIVE);
-}
-
-/* reset DPRAM */
-static inline void softing_set_reset_dpram(struct softing *card)
-{
-	if (card->pdat->generation >= 2) {
-		spin_lock_bh(&card->spin);
-		iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) & ~1,
-				&card->dpram[DPRAM_V2_RESET]);
-		spin_unlock_bh(&card->spin);
-	}
-}
-
-static inline void softing_clr_reset_dpram(struct softing *card)
-{
-	if (card->pdat->generation >= 2) {
-		spin_lock_bh(&card->spin);
-		iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) | 1,
-				&card->dpram[DPRAM_V2_RESET]);
-		spin_unlock_bh(&card->spin);
-	}
-}
-
-/* trigger the tx queue-ing */
-static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
-		struct net_device *dev)
-{
-	struct softing_priv *priv = netdev_priv(dev);
-	struct softing *card = priv->card;
-	int ret;
-	uint8_t *ptr;
-	uint8_t fifo_wr, fifo_rd;
-	struct can_frame *cf = (struct can_frame *)skb->data;
-	uint8_t buf[DPRAM_TX_SIZE];
-
-	if (can_dev_dropped_skb(dev, skb))
-		return NETDEV_TX_OK;
-
-	spin_lock(&card->spin);
-
-	ret = NETDEV_TX_BUSY;
-	if (!card->fw.up ||
-			(card->tx.pending >= TXMAX) ||
-			(priv->tx.pending >= TX_ECHO_SKB_MAX))
-		goto xmit_done;
-	fifo_wr = ioread8(&card->dpram[DPRAM_TX_WR]);
-	fifo_rd = ioread8(&card->dpram[DPRAM_TX_RD]);
-	if (fifo_wr == fifo_rd)
-		/* fifo full */
-		goto xmit_done;
-	memset(buf, 0, sizeof(buf));
-	ptr = buf;
-	*ptr = CMD_TX;
-	if (cf->can_id & CAN_RTR_FLAG)
-		*ptr |= CMD_RTR;
-	if (cf->can_id & CAN_EFF_FLAG)
-		*ptr |= CMD_XTD;
-	if (priv->index)
-		*ptr |= CMD_BUS2;
-	++ptr;
-	*ptr++ = cf->len;
-	*ptr++ = (cf->can_id >> 0);
-	*ptr++ = (cf->can_id >> 8);
-	if (cf->can_id & CAN_EFF_FLAG) {
-		*ptr++ = (cf->can_id >> 16);
-		*ptr++ = (cf->can_id >> 24);
-	} else {
-		/* increment 1, not 2 as you might think */
-		ptr += 1;
-	}
-	if (!(cf->can_id & CAN_RTR_FLAG))
-		memcpy(ptr, &cf->data[0], cf->len);
-	memcpy_toio(&card->dpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr],
-			buf, DPRAM_TX_SIZE);
-	if (++fifo_wr >= DPRAM_TX_CNT)
-		fifo_wr = 0;
-	iowrite8(fifo_wr, &card->dpram[DPRAM_TX_WR]);
-	card->tx.last_bus = priv->index;
-	++card->tx.pending;
-	++priv->tx.pending;
-	can_put_echo_skb(skb, dev, priv->tx.echo_put, 0);
-	++priv->tx.echo_put;
-	if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
-		priv->tx.echo_put = 0;
-	/* can_put_echo_skb() saves the skb, safe to return TX_OK */
-	ret = NETDEV_TX_OK;
-xmit_done:
-	spin_unlock(&card->spin);
-	if (card->tx.pending >= TXMAX) {
-		int j;
-		for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-			if (card->net[j])
-				netif_stop_queue(card->net[j]);
-		}
-	}
-	if (ret != NETDEV_TX_OK)
-		netif_stop_queue(dev);
-
-	return ret;
-}
-
-/*
- * shortcut for skb delivery
- */
-int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
-		ktime_t ktime)
-{
-	struct sk_buff *skb;
-	struct can_frame *cf;
-
-	skb = alloc_can_skb(netdev, &cf);
-	if (!skb)
-		return -ENOMEM;
-	memcpy(cf, msg, sizeof(*msg));
-	skb->tstamp = ktime;
-	return netif_rx(skb);
-}
-
-/*
- * softing_handle_1
- * pop 1 entry from the DPRAM queue, and process
- */
-static int softing_handle_1(struct softing *card)
-{
-	struct net_device *netdev;
-	struct softing_priv *priv;
-	ktime_t ktime;
-	struct can_frame msg;
-	int cnt = 0, lost_msg;
-	uint8_t fifo_rd, fifo_wr, cmd;
-	uint8_t *ptr;
-	uint32_t tmp_u32;
-	uint8_t buf[DPRAM_RX_SIZE];
-
-	memset(&msg, 0, sizeof(msg));
-	/* test for lost msgs */
-	lost_msg = ioread8(&card->dpram[DPRAM_RX_LOST]);
-	if (lost_msg) {
-		int j;
-		/* reset condition */
-		iowrite8(0, &card->dpram[DPRAM_RX_LOST]);
-		/* prepare msg */
-		msg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
-		msg.len = CAN_ERR_DLC;
-		msg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
-		/*
-		 * service to all buses, we don't know which it was applicable
-		 * but only service buses that are online
-		 */
-		for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-			netdev = card->net[j];
-			if (!netdev)
-				continue;
-			if (!canif_is_active(netdev))
-				/* a dead bus has no overflows */
-				continue;
-			++netdev->stats.rx_over_errors;
-			softing_netdev_rx(netdev, &msg, 0);
-		}
-		/* prepare for other use */
-		memset(&msg, 0, sizeof(msg));
-		++cnt;
-	}
-
-	fifo_rd = ioread8(&card->dpram[DPRAM_RX_RD]);
-	fifo_wr = ioread8(&card->dpram[DPRAM_RX_WR]);
-
-	if (++fifo_rd >= DPRAM_RX_CNT)
-		fifo_rd = 0;
-	if (fifo_wr == fifo_rd)
-		return cnt;
-
-	memcpy_fromio(buf, &card->dpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd],
-			DPRAM_RX_SIZE);
-	mb();
-	/* trigger dual port RAM */
-	iowrite8(fifo_rd, &card->dpram[DPRAM_RX_RD]);
-
-	ptr = buf;
-	cmd = *ptr++;
-	if (cmd == 0xff)
-		/* not quite useful, probably the card has got out */
-		return 0;
-	netdev = card->net[0];
-	if (cmd & CMD_BUS2)
-		netdev = card->net[1];
-	priv = netdev_priv(netdev);
-
-	if (cmd & CMD_ERR) {
-		uint8_t can_state, state;
-
-		state = *ptr++;
-
-		msg.can_id = CAN_ERR_FLAG;
-		msg.len = CAN_ERR_DLC;
-
-		if (state & SF_MASK_BUSOFF) {
-			can_state = CAN_STATE_BUS_OFF;
-			msg.can_id |= CAN_ERR_BUSOFF;
-			state = STATE_BUSOFF;
-		} else if (state & SF_MASK_EPASSIVE) {
-			can_state = CAN_STATE_ERROR_PASSIVE;
-			msg.can_id |= CAN_ERR_CRTL;
-			msg.data[1] = CAN_ERR_CRTL_TX_PASSIVE;
-			state = STATE_EPASSIVE;
-		} else {
-			can_state = CAN_STATE_ERROR_ACTIVE;
-			msg.can_id |= CAN_ERR_CRTL;
-			state = STATE_EACTIVE;
-		}
-		/* update DPRAM */
-		iowrite8(state, &card->dpram[priv->index ?
-				DPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]);
-		/* timestamp */
-		tmp_u32 = le32_to_cpup((void *)ptr);
-		ktime = softing_raw2ktime(card, tmp_u32);
-
-		++netdev->stats.rx_errors;
-		/* update internal status */
-		if (can_state != priv->can.state) {
-			priv->can.state = can_state;
-			if (can_state == CAN_STATE_ERROR_PASSIVE)
-				++priv->can.can_stats.error_passive;
-			else if (can_state == CAN_STATE_BUS_OFF) {
-				/* this calls can_close_cleanup() */
-				++priv->can.can_stats.bus_off;
-				can_bus_off(netdev);
-				netif_stop_queue(netdev);
-			}
-			/* trigger socketcan */
-			softing_netdev_rx(netdev, &msg, ktime);
-		}
-
-	} else {
-		if (cmd & CMD_RTR)
-			msg.can_id |= CAN_RTR_FLAG;
-		msg.len = can_cc_dlc2len(*ptr++);
-		if (cmd & CMD_XTD) {
-			msg.can_id |= CAN_EFF_FLAG;
-			msg.can_id |= le32_to_cpup((void *)ptr);
-			ptr += 4;
-		} else {
-			msg.can_id |= le16_to_cpup((void *)ptr);
-			ptr += 2;
-		}
-		/* timestamp */
-		tmp_u32 = le32_to_cpup((void *)ptr);
-		ptr += 4;
-		ktime = softing_raw2ktime(card, tmp_u32);
-		if (!(msg.can_id & CAN_RTR_FLAG))
-			memcpy(&msg.data[0], ptr, 8);
-		/* update socket */
-		if (cmd & CMD_ACK) {
-			/* acknowledge, was tx msg */
-			struct sk_buff *skb;
-			skb = priv->can.echo_skb[priv->tx.echo_get];
-			if (skb)
-				skb->tstamp = ktime;
-			++netdev->stats.tx_packets;
-			netdev->stats.tx_bytes +=
-				can_get_echo_skb(netdev, priv->tx.echo_get,
-						 NULL);
-			++priv->tx.echo_get;
-			if (priv->tx.echo_get >= TX_ECHO_SKB_MAX)
-				priv->tx.echo_get = 0;
-			if (priv->tx.pending)
-				--priv->tx.pending;
-			if (card->tx.pending)
-				--card->tx.pending;
-		} else {
-			int ret;
-
-			ret = softing_netdev_rx(netdev, &msg, ktime);
-			if (ret == NET_RX_SUCCESS) {
-				++netdev->stats.rx_packets;
-				if (!(msg.can_id & CAN_RTR_FLAG))
-					netdev->stats.rx_bytes += msg.len;
-			} else {
-				++netdev->stats.rx_dropped;
-			}
-		}
-	}
-	++cnt;
-	return cnt;
-}
-
-/*
- * real interrupt handler
- */
-static irqreturn_t softing_irq_thread(int irq, void *dev_id)
-{
-	struct softing *card = (struct softing *)dev_id;
-	struct net_device *netdev;
-	struct softing_priv *priv;
-	int j, offset, work_done;
-
-	work_done = 0;
-	spin_lock_bh(&card->spin);
-	while (softing_handle_1(card) > 0) {
-		++card->irq.svc_count;
-		++work_done;
-	}
-	spin_unlock_bh(&card->spin);
-	/* resume tx queue's */
-	offset = card->tx.last_bus;
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (card->tx.pending >= TXMAX)
-			break;
-		netdev = card->net[(j + offset + 1) % card->pdat->nbus];
-		if (!netdev)
-			continue;
-		priv = netdev_priv(netdev);
-		if (!canif_is_active(netdev))
-			/* it makes no sense to wake dead buses */
-			continue;
-		if (priv->tx.pending >= TX_ECHO_SKB_MAX)
-			continue;
-		++work_done;
-		netif_wake_queue(netdev);
-	}
-	return work_done ? IRQ_HANDLED : IRQ_NONE;
-}
-
-/*
- * interrupt routines:
- * schedule the 'real interrupt handler'
- */
-static irqreturn_t softing_irq_v2(int irq, void *dev_id)
-{
-	struct softing *card = (struct softing *)dev_id;
-	uint8_t ir;
-
-	ir = ioread8(&card->dpram[DPRAM_V2_IRQ_TOHOST]);
-	iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);
-	return (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE;
-}
-
-static irqreturn_t softing_irq_v1(int irq, void *dev_id)
-{
-	struct softing *card = (struct softing *)dev_id;
-	uint8_t ir;
-
-	ir = ioread8(&card->dpram[DPRAM_IRQ_TOHOST]);
-	iowrite8(0, &card->dpram[DPRAM_IRQ_TOHOST]);
-	return ir ? IRQ_WAKE_THREAD : IRQ_NONE;
-}
-
-/*
- * netdev/candev interoperability
- */
-static int softing_netdev_open(struct net_device *ndev)
-{
-	int ret;
-
-	/* check or determine and set bittime */
-	ret = open_candev(ndev);
-	if (ret)
-		return ret;
-
-	ret = softing_startstop(ndev, 1);
-	if (ret < 0)
-		close_candev(ndev);
-
-	return ret;
-}
-
-static int softing_netdev_stop(struct net_device *ndev)
-{
-	netif_stop_queue(ndev);
-
-	/* softing cycle does close_candev() */
-	return softing_startstop(ndev, 0);
-}
-
-static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode)
-{
-	int ret;
-
-	switch (mode) {
-	case CAN_MODE_START:
-		/* softing_startstop does close_candev() */
-		ret = softing_startstop(ndev, 1);
-		return ret;
-	case CAN_MODE_STOP:
-	case CAN_MODE_SLEEP:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
-/*
- * Softing device management helpers
- */
-int softing_enable_irq(struct softing *card, int enable)
-{
-	int ret;
-
-	if (!card->irq.nr) {
-		return 0;
-	} else if (card->irq.requested && !enable) {
-		free_irq(card->irq.nr, card);
-		card->irq.requested = 0;
-	} else if (!card->irq.requested && enable) {
-		ret = request_threaded_irq(card->irq.nr,
-				(card->pdat->generation >= 2) ?
-					softing_irq_v2 : softing_irq_v1,
-				softing_irq_thread, IRQF_SHARED,
-				dev_name(&card->pdev->dev), card);
-		if (ret) {
-			dev_alert(&card->pdev->dev,
-					"request_threaded_irq(%u) failed\n",
-					card->irq.nr);
-			return ret;
-		}
-		card->irq.requested = 1;
-	}
-	return 0;
-}
-
-static void softing_card_shutdown(struct softing *card)
-{
-	int fw_up = 0;
-
-	if (mutex_lock_interruptible(&card->fw.lock)) {
-		/* return -ERESTARTSYS */;
-	}
-	fw_up = card->fw.up;
-	card->fw.up = 0;
-
-	if (card->irq.requested && card->irq.nr) {
-		free_irq(card->irq.nr, card);
-		card->irq.requested = 0;
-	}
-	if (fw_up) {
-		if (card->pdat->enable_irq)
-			card->pdat->enable_irq(card->pdev, 0);
-		softing_set_reset_dpram(card);
-		if (card->pdat->reset)
-			card->pdat->reset(card->pdev, 1);
-	}
-	mutex_unlock(&card->fw.lock);
-}
-
-static int softing_card_boot(struct softing *card)
-{
-	int ret, j;
-	static const uint8_t stream[] = {
-		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, };
-	unsigned char back[sizeof(stream)];
-
-	if (mutex_lock_interruptible(&card->fw.lock))
-		return -ERESTARTSYS;
-	if (card->fw.up) {
-		mutex_unlock(&card->fw.lock);
-		return 0;
-	}
-	/* reset board */
-	if (card->pdat->enable_irq)
-		card->pdat->enable_irq(card->pdev, 1);
-	/* boot card */
-	softing_set_reset_dpram(card);
-	if (card->pdat->reset)
-		card->pdat->reset(card->pdev, 1);
-	for (j = 0; (j + sizeof(stream)) < card->dpram_size;
-			j += sizeof(stream)) {
-
-		memcpy_toio(&card->dpram[j], stream, sizeof(stream));
-		/* flush IO cache */
-		mb();
-		memcpy_fromio(back, &card->dpram[j], sizeof(stream));
-
-		if (!memcmp(back, stream, sizeof(stream)))
-			continue;
-		/* memory is not equal */
-		dev_alert(&card->pdev->dev, "dpram failed at 0x%04x\n", j);
-		ret = -EIO;
-		goto failed;
-	}
-	wmb();
-	/* load boot firmware */
-	ret = softing_load_fw(card->pdat->boot.fw, card, card->dpram,
-				card->dpram_size,
-				card->pdat->boot.offs - card->pdat->boot.addr);
-	if (ret < 0)
-		goto failed;
-	/* load loader firmware */
-	ret = softing_load_fw(card->pdat->load.fw, card, card->dpram,
-				card->dpram_size,
-				card->pdat->load.offs - card->pdat->load.addr);
-	if (ret < 0)
-		goto failed;
-
-	if (card->pdat->reset)
-		card->pdat->reset(card->pdev, 0);
-	softing_clr_reset_dpram(card);
-	ret = softing_bootloader_command(card, 0, "card boot");
-	if (ret < 0)
-		goto failed;
-	ret = softing_load_app_fw(card->pdat->app.fw, card);
-	if (ret < 0)
-		goto failed;
-
-	ret = softing_chip_poweron(card);
-	if (ret < 0)
-		goto failed;
-
-	card->fw.up = 1;
-	mutex_unlock(&card->fw.lock);
-	return 0;
-failed:
-	card->fw.up = 0;
-	if (card->pdat->enable_irq)
-		card->pdat->enable_irq(card->pdev, 0);
-	softing_set_reset_dpram(card);
-	if (card->pdat->reset)
-		card->pdat->reset(card->pdev, 1);
-	mutex_unlock(&card->fw.lock);
-	return ret;
-}
-
-/*
- * netdev sysfs
- */
-static ssize_t show_chip(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct net_device *ndev = to_net_dev(dev);
-	struct softing_priv *priv = netdev2softing(ndev);
-
-	return sprintf(buf, "%i\n", priv->chip);
-}
-
-static ssize_t show_output(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct net_device *ndev = to_net_dev(dev);
-	struct softing_priv *priv = netdev2softing(ndev);
-
-	return sprintf(buf, "0x%02x\n", priv->output);
-}
-
-static ssize_t store_output(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct net_device *ndev = to_net_dev(dev);
-	struct softing_priv *priv = netdev2softing(ndev);
-	struct softing *card = priv->card;
-	unsigned long val;
-	int ret;
-
-	ret = kstrtoul(buf, 0, &val);
-	if (ret < 0)
-		return ret;
-	val &= 0xFF;
-
-	ret = mutex_lock_interruptible(&card->fw.lock);
-	if (ret)
-		return -ERESTARTSYS;
-	if (netif_running(ndev)) {
-		mutex_unlock(&card->fw.lock);
-		return -EBUSY;
-	}
-	priv->output = val;
-	mutex_unlock(&card->fw.lock);
-	return count;
-}
-
-static const DEVICE_ATTR(chip, 0444, show_chip, NULL);
-static const DEVICE_ATTR(output, 0644, show_output, store_output);
-
-static const struct attribute *const netdev_sysfs_attrs[] = {
-	&dev_attr_chip.attr,
-	&dev_attr_output.attr,
-	NULL,
-};
-static const struct attribute_group netdev_sysfs_group = {
-	.name = NULL,
-	.attrs = (struct attribute **)netdev_sysfs_attrs,
-};
-
-static const struct net_device_ops softing_netdev_ops = {
-	.ndo_open = softing_netdev_open,
-	.ndo_stop = softing_netdev_stop,
-	.ndo_start_xmit	= softing_netdev_start_xmit,
-};
-
-static const struct ethtool_ops softing_ethtool_ops = {
-	.get_ts_info = ethtool_op_get_ts_info,
-};
-
-static const struct can_bittiming_const softing_btr_const = {
-	.name = KBUILD_MODNAME,
-	.tseg1_min = 1,
-	.tseg1_max = 16,
-	.tseg2_min = 1,
-	.tseg2_max = 8,
-	.sjw_max = 4, /* overruled */
-	.brp_min = 1,
-	.brp_max = 32, /* overruled */
-	.brp_inc = 1,
-};
-
-
-static struct net_device *softing_netdev_create(struct softing *card,
-						uint16_t chip_id)
-{
-	struct net_device *netdev;
-	struct softing_priv *priv;
-
-	netdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
-	if (!netdev) {
-		dev_alert(&card->pdev->dev, "alloc_candev failed\n");
-		return NULL;
-	}
-	priv = netdev_priv(netdev);
-	priv->netdev = netdev;
-	priv->card = card;
-	memcpy(&priv->btr_const, &softing_btr_const, sizeof(priv->btr_const));
-	priv->btr_const.brp_max = card->pdat->max_brp;
-	priv->btr_const.sjw_max = card->pdat->max_sjw;
-	priv->can.bittiming_const = &priv->btr_const;
-	priv->can.clock.freq = 8000000;
-	priv->chip = chip_id;
-	priv->output = softing_default_output(netdev);
-	SET_NETDEV_DEV(netdev, &card->pdev->dev);
-
-	netdev->flags |= IFF_ECHO;
-	netdev->netdev_ops = &softing_netdev_ops;
-	netdev->ethtool_ops = &softing_ethtool_ops;
-	priv->can.do_set_mode = softing_candev_set_mode;
-	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
-
-	return netdev;
-}
-
-static int softing_netdev_register(struct net_device *netdev)
-{
-	int ret;
-
-	ret = register_candev(netdev);
-	if (ret) {
-		dev_alert(&netdev->dev, "register failed\n");
-		return ret;
-	}
-	if (sysfs_create_group(&netdev->dev.kobj, &netdev_sysfs_group) < 0)
-		netdev_alert(netdev, "sysfs group failed\n");
-
-	return 0;
-}
-
-static void softing_netdev_cleanup(struct net_device *netdev)
-{
-	sysfs_remove_group(&netdev->dev.kobj, &netdev_sysfs_group);
-	unregister_candev(netdev);
-	free_candev(netdev);
-}
-
-/*
- * sysfs for Platform device
- */
-#define DEV_ATTR_RO(name, member) \
-static ssize_t show_##name(struct device *dev, \
-		struct device_attribute *attr, char *buf) \
-{ \
-	struct softing *card = dev_get_drvdata(dev); \
-	return sprintf(buf, "%u\n", card->member); \
-} \
-static DEVICE_ATTR(name, 0444, show_##name, NULL)
-
-#define DEV_ATTR_RO_STR(name, member) \
-static ssize_t show_##name(struct device *dev, \
-		struct device_attribute *attr, char *buf) \
-{ \
-	struct softing *card = dev_get_drvdata(dev); \
-	return sprintf(buf, "%s\n", card->member); \
-} \
-static DEVICE_ATTR(name, 0444, show_##name, NULL)
-
-DEV_ATTR_RO(serial, id.serial);
-DEV_ATTR_RO_STR(firmware, pdat->app.fw);
-DEV_ATTR_RO(firmware_version, id.fw_version);
-DEV_ATTR_RO_STR(hardware, pdat->name);
-DEV_ATTR_RO(hardware_version, id.hw_version);
-DEV_ATTR_RO(license, id.license);
-
-static struct attribute *softing_pdev_attrs[] = {
-	&dev_attr_serial.attr,
-	&dev_attr_firmware.attr,
-	&dev_attr_firmware_version.attr,
-	&dev_attr_hardware.attr,
-	&dev_attr_hardware_version.attr,
-	&dev_attr_license.attr,
-	NULL,
-};
-
-static const struct attribute_group softing_pdev_group = {
-	.name = NULL,
-	.attrs = softing_pdev_attrs,
-};
-
-/*
- * platform driver
- */
-static void softing_pdev_remove(struct platform_device *pdev)
-{
-	struct softing *card = platform_get_drvdata(pdev);
-	int j;
-
-	/* first, disable card*/
-	softing_card_shutdown(card);
-
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (!card->net[j])
-			continue;
-		softing_netdev_cleanup(card->net[j]);
-		card->net[j] = NULL;
-	}
-	sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
-
-	iounmap(card->dpram);
-	kfree(card);
-}
-
-static int softing_pdev_probe(struct platform_device *pdev)
-{
-	const struct softing_platform_data *pdat = dev_get_platdata(&pdev->dev);
-	struct softing *card;
-	struct net_device *netdev;
-	struct softing_priv *priv;
-	struct resource *pres;
-	int ret;
-	int j;
-
-	if (!pdat) {
-		dev_warn(&pdev->dev, "no platform data\n");
-		return -EINVAL;
-	}
-	if (pdat->nbus > ARRAY_SIZE(card->net)) {
-		dev_warn(&pdev->dev, "%u nets??\n", pdat->nbus);
-		return -EINVAL;
-	}
-
-	card = kzalloc_obj(*card);
-	if (!card)
-		return -ENOMEM;
-	card->pdat = pdat;
-	card->pdev = pdev;
-	platform_set_drvdata(pdev, card);
-	mutex_init(&card->fw.lock);
-	spin_lock_init(&card->spin);
-
-	ret = -EINVAL;
-	pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!pres)
-		goto platform_resource_failed;
-	card->dpram_phys = pres->start;
-	card->dpram_size = resource_size(pres);
-	card->dpram = ioremap(card->dpram_phys, card->dpram_size);
-	if (!card->dpram) {
-		dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
-		goto ioremap_failed;
-	}
-
-	pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (pres)
-		card->irq.nr = pres->start;
-
-	/* reset card */
-	ret = softing_card_boot(card);
-	if (ret < 0) {
-		dev_alert(&pdev->dev, "failed to boot\n");
-		goto boot_failed;
-	}
-
-	/* only now, the chip's are known */
-	card->id.freq = card->pdat->freq;
-
-	ret = sysfs_create_group(&pdev->dev.kobj, &softing_pdev_group);
-	if (ret < 0) {
-		dev_alert(&card->pdev->dev, "sysfs failed\n");
-		goto sysfs_failed;
-	}
-
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		card->net[j] = netdev =
-			softing_netdev_create(card, card->id.chip[j]);
-		if (!netdev) {
-			dev_alert(&pdev->dev, "failed to make can[%i]", j);
-			ret = -ENOMEM;
-			goto netdev_failed;
-		}
-		netdev->dev_id = j;
-		priv = netdev_priv(card->net[j]);
-		priv->index = j;
-		ret = softing_netdev_register(netdev);
-		if (ret) {
-			free_candev(netdev);
-			card->net[j] = NULL;
-			dev_alert(&card->pdev->dev,
-					"failed to register can[%i]\n", j);
-			goto netdev_failed;
-		}
-	}
-	dev_info(&card->pdev->dev, "%s ready.\n", card->pdat->name);
-	return 0;
-
-netdev_failed:
-	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {
-		if (!card->net[j])
-			continue;
-		softing_netdev_cleanup(card->net[j]);
-	}
-	sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group);
-sysfs_failed:
-	softing_card_shutdown(card);
-boot_failed:
-	iounmap(card->dpram);
-ioremap_failed:
-platform_resource_failed:
-	kfree(card);
-	return ret;
-}
-
-static struct platform_driver softing_driver = {
-	.driver = {
-		.name = KBUILD_MODNAME,
-	},
-	.probe = softing_pdev_probe,
-	.remove = softing_pdev_remove,
-};
-
-module_platform_driver(softing_driver);
-
-MODULE_ALIAS("platform:softing");
-MODULE_DESCRIPTION("Softing DPRAM CAN driver");
-MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h
deleted file mode 100644
index cd8d7904c5f08..0000000000000
--- a/drivers/net/can/softing/softing_platform.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/platform_device.h>
-
-#ifndef _SOFTING_DEVICE_H_
-#define _SOFTING_DEVICE_H_
-
-/* softing firmware directory prefix */
-#define fw_dir "softing-4.6/"
-
-struct softing_platform_data {
-	unsigned int manf;
-	unsigned int prod;
-	/*
-	 * generation
-	 * 1st with NEC or SJA1000
-	 * 8bit, exclusive interrupt, ...
-	 * 2nd only SJA1000
-	 * 16bit, shared interrupt
-	 */
-	int generation;
-	int nbus; /* # buses on device */
-	unsigned int freq; /* operating frequency in Hz */
-	unsigned int max_brp;
-	unsigned int max_sjw;
-	unsigned long dpram_size;
-	const char *name;
-	struct {
-		unsigned long offs;
-		unsigned long addr;
-		const char *fw;
-	} boot, load, app;
-	/*
-	 * reset() function
-	 * bring pdev in or out of reset, depending on value
-	 */
-	int (*reset)(struct platform_device *pdev, int value);
-	int (*enable_irq)(struct platform_device *pdev, int value);
-};
-
-#endif
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index ae90e6716de5b..076a3efa1bfff 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -972,7 +972,7 @@ static void hi3110_can_remove(struct spi_device *spi)
 	free_candev(net);
 }
 
-static int __maybe_unused hi3110_can_suspend(struct device *dev)
+static int hi3110_can_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct hi3110_priv *priv = spi_get_drvdata(spi);
@@ -1002,7 +1002,7 @@ static int __maybe_unused hi3110_can_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused hi3110_can_resume(struct device *dev)
+static int hi3110_can_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct hi3110_priv *priv = spi_get_drvdata(spi);
@@ -1022,13 +1022,13 @@ static int __maybe_unused hi3110_can_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend, hi3110_can_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend, hi3110_can_resume);
 
 static struct spi_driver hi3110_can_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
 		.of_match_table = hi3110_of_match,
-		.pm = &hi3110_can_pm_ops,
+		.pm = pm_sleep_ptr(&hi3110_can_pm_ops),
 	},
 	.id_table = hi3110_id_table,
 	.probe = hi3110_can_probe,
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 0d0190ae094a1..d971890487b6c 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1490,7 +1490,7 @@ static void mcp251x_can_remove(struct spi_device *spi)
 	free_candev(net);
 }
 
-static int __maybe_unused mcp251x_can_suspend(struct device *dev)
+static int mcp251x_can_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_priv *priv = spi_get_drvdata(spi);
@@ -1517,7 +1517,7 @@ static int __maybe_unused mcp251x_can_suspend(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused mcp251x_can_resume(struct device *dev)
+static int mcp251x_can_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_priv *priv = spi_get_drvdata(spi);
@@ -1551,14 +1551,14 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
+static DEFINE_SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
 	mcp251x_can_resume);
 
 static struct spi_driver mcp251x_can_driver = {
 	.driver = {
 		.name = DEVICE_NAME,
 		.of_match_table = mcp251x_of_match,
-		.pm = &mcp251x_can_pm_ops,
+		.pm = pm_sleep_ptr(&mcp251x_can_pm_ops),
 	},
 	.id_table = mcp251x_id_table,
 	.probe = mcp251x_can_probe,
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index f441f2265299e..8759bc05bd8f0 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -2213,6 +2213,7 @@ MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table);
 
 static int mcp251xfd_probe(struct spi_device *spi)
 {
+	const struct mcp251xfd_devtype_data *devtype_data;
 	struct net_device *ndev;
 	struct mcp251xfd_priv *priv;
 	struct gpio_desc *rx_int;
@@ -2222,6 +2223,10 @@ static int mcp251xfd_probe(struct spi_device *spi)
 	u32 freq = 0;
 	int err;
 
+	devtype_data = spi_get_device_match_data(spi);
+	if (!devtype_data)
+		return -ENODATA;
+
 	if (!spi->irq)
 		return dev_err_probe(&spi->dev, -ENXIO,
 				     "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n");
@@ -2307,7 +2312,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
 	priv->reg_vdd = reg_vdd;
 	priv->reg_xceiver = reg_xceiver;
 	priv->xstbyen = device_property_present(&spi->dev, "microchip,xstbyen");
-	priv->devtype_data = *(struct mcp251xfd_devtype_data *)spi_get_device_match_data(spi);
+	priv->devtype_data = *devtype_data;
 
 	/* Errata Reference:
 	 * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789E 4.,
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index af52285d5a4e0..76db6d09d1e6b 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -812,9 +812,12 @@ MODULE_DEVICE_TABLE(of, sun4ican_of_match);
 static void sun4ican_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+	struct sun4ican_priv *priv = netdev_priv(dev);
+	struct clk *clk = priv->clk;
 
 	unregister_netdev(dev);
 	free_candev(dev);
+	clk_put(clk);
 }
 
 static int sun4ican_probe(struct platform_device *pdev)
@@ -854,13 +857,13 @@ static int sun4ican_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		err = -ENODEV;
-		goto exit;
+		goto exit_put_clk;
 	}
 
 	addr = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(addr)) {
 		err = PTR_ERR(addr);
-		goto exit;
+		goto exit_put_clk;
 	}
 
 	dev = alloc_candev(sizeof(struct sun4ican_priv), 1);
@@ -868,7 +871,7 @@ static int sun4ican_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev,
 			"could not allocate memory for CAN device\n");
 		err = -ENOMEM;
-		goto exit;
+		goto exit_put_clk;
 	}
 
 	dev->netdev_ops = &sun4ican_netdev_ops;
@@ -908,6 +911,8 @@ static int sun4ican_probe(struct platform_device *pdev)
 
 exit_free:
 	free_candev(dev);
+exit_put_clk:
+	clk_put(clk);
 exit:
 	return err;
 }
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 24cf8f651f8f1..2d31f0b86859c 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -748,7 +748,7 @@ static void unlink_all_urbs(struct ems_usb *dev)
 {
 	int i;
 
-	usb_unlink_urb(dev->intr_urb);
+	usb_kill_urb(dev->intr_urb);
 
 	usb_kill_anchored_urbs(&dev->rx_submitted);
 
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
index 46a1b6907a500..2e862120ec3ff 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
@@ -161,7 +161,6 @@ struct kvaser_usb_net_priv {
  * @dev_get_data_busparams:	readback data busparams
  * @dev_get_berr_counter:	used for can.do_get_berr_counter
  *
- * @dev_setup_endpoints:	setup USB in and out endpoints
  * @dev_init_card:		initialize card
  * @dev_init_channel:		initialize channel
  * @dev_remove_channel:		uninitialize channel
@@ -189,7 +188,6 @@ struct kvaser_usb_dev_ops {
 	int (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv);
 	int (*dev_get_berr_counter)(const struct net_device *netdev,
 				    struct can_berr_counter *bec);
-	int (*dev_setup_endpoints)(struct kvaser_usb *dev);
 	int (*dev_init_card)(struct kvaser_usb *dev);
 	int (*dev_init_channel)(struct kvaser_usb_net_priv *priv);
 	void (*dev_remove_channel)(struct kvaser_usb_net_priv *priv);
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index d0a2a2a33c1c8..9687dfb89b4cc 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -926,6 +926,23 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
 	return err;
 }
 
+static int kvaser_usb_setup_endpoints(struct kvaser_usb *dev)
+{
+	struct usb_host_interface *iface_desc;
+	int ret;
+
+	iface_desc = dev->intf->cur_altsetting;
+
+	/* use first bulk endpoint for in and out */
+	ret = usb_find_common_endpoints(iface_desc, &dev->bulk_in,
+					&dev->bulk_out, NULL, NULL);
+
+	if (ret)
+		return -ENODEV;
+
+	return 0;
+}
+
 static int kvaser_usb_probe(struct usb_interface *intf,
 			    const struct usb_device_id *id)
 {
@@ -949,7 +966,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,
 	dev->driver_info = driver_info;
 	ops = driver_info->ops;
 
-	err = ops->dev_setup_endpoints(dev);
+	err = kvaser_usb_setup_endpoints(dev);
 	if (err) {
 		dev_err_probe(&intf->dev, err, "Cannot get usb endpoint(s)");
 		goto free_devlink;
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index efbb7bed34c9d..2220d197abb55 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -37,9 +37,6 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_kcan;
 static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc;
 static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt;
 
-#define KVASER_USB_HYDRA_BULK_EP_IN_ADDR	0x82
-#define KVASER_USB_HYDRA_BULK_EP_OUT_ADDR	0x02
-
 #define KVASER_USB_HYDRA_MAX_TRANSID		0xff
 #define KVASER_USB_HYDRA_MIN_TRANSID		0x01
 
@@ -536,6 +533,82 @@ static size_t kvaser_usb_hydra_cmd_size(struct kvaser_cmd *cmd)
 	return ret;
 }
 
+/* -EAGAIN means incomplete; -EINVAL rejects an invalid command length. */
+static int kvaser_usb_hydra_cmd_size_rx(struct kvaser_cmd *cmd,
+					size_t remaining, size_t *cmd_len)
+{
+	if (remaining < sizeof(cmd->header.cmd_no))
+		return -EAGAIN;
+
+	if (cmd->header.cmd_no == CMD_EXTENDED &&
+	    remaining < offsetof(struct kvaser_cmd_ext, cmd_no_ext))
+		return -EAGAIN;
+
+	*cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+	if (cmd->header.cmd_no != CMD_EXTENDED)
+		return 0;
+
+	if (*cmd_len < offsetof(struct kvaser_cmd_ext, rx_can) ||
+	    *cmd_len > KVASER_USB_HYDRA_MAX_CMD_LEN)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int kvaser_usb_hydra_verify_cmd_size(const struct kvaser_cmd *cmd,
+					    size_t cmd_len)
+{
+	const struct kvaser_cmd_ext *cmd_ext;
+	size_t min_len;
+
+	if (cmd->header.cmd_no != CMD_EXTENDED)
+		return 0;
+
+	cmd_ext = (const struct kvaser_cmd_ext *)cmd;
+
+	/* Keep this switch in sync with kvaser_usb_hydra_handle_cmd_ext(). */
+	switch (cmd_ext->cmd_no_ext) {
+	case CMD_TX_ACKNOWLEDGE_FD:
+		min_len = offsetof(struct kvaser_cmd_ext, tx_ack.timestamp) +
+			  sizeof(cmd_ext->tx_ack.timestamp);
+		break;
+
+	case CMD_RX_MESSAGE_FD: {
+		u32 flags;
+
+		min_len = offsetof(struct kvaser_cmd_ext, rx_can.kcan_payload);
+		if (cmd_len < min_len)
+			return -EINVAL;
+
+		flags = le32_to_cpu(cmd_ext->rx_can.flags);
+		if (flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {
+			min_len += sizeof(cmd_ext->rx_can.err_frame_data);
+		} else if (!(flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME)) {
+			u32 kcan_header;
+			u8 dlc;
+
+			kcan_header = le32_to_cpu(cmd_ext->rx_can.kcan_header);
+			dlc = (kcan_header & KVASER_USB_KCAN_DATA_DLC_MASK) >>
+				KVASER_USB_KCAN_DATA_DLC_SHIFT;
+
+			if (flags & KVASER_USB_HYDRA_CF_FLAG_FDF)
+				min_len += can_fd_dlc2len(dlc);
+			else
+				min_len += can_cc_dlc2len(dlc);
+		}
+		break;
+	}
+
+	default:
+		return 0;
+	}
+
+	if (cmd_len < min_len)
+		return -EINVAL;
+
+	return 0;
+}
+
 static struct kvaser_usb_net_priv *
 kvaser_usb_hydra_net_priv_from_cmd(const struct kvaser_usb *dev,
 				   const struct kvaser_cmd *cmd)
@@ -675,8 +748,9 @@ static int kvaser_usb_hydra_wait_cmd(const struct kvaser_usb *dev, u8 cmd_no,
 			size_t cmd_len;
 
 			tmp_cmd = buf + pos;
-			cmd_len = kvaser_usb_hydra_cmd_size(tmp_cmd);
-			if (pos + cmd_len > actual_len) {
+			err = kvaser_usb_hydra_cmd_size_rx(tmp_cmd, actual_len - pos, &cmd_len);
+			if (err || pos + cmd_len > actual_len ||
+			    kvaser_usb_hydra_verify_cmd_size(tmp_cmd, cmd_len)) {
 				dev_err_ratelimited(&dev->intf->dev,
 						    "Format error\n");
 				break;
@@ -1733,32 +1807,6 @@ static int kvaser_usb_hydra_get_berr_counter(const struct net_device *netdev,
 	return 0;
 }
 
-static int kvaser_usb_hydra_setup_endpoints(struct kvaser_usb *dev)
-{
-	const struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *ep;
-	int i;
-
-	iface_desc = dev->intf->cur_altsetting;
-
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		ep = &iface_desc->endpoint[i].desc;
-
-		if (!dev->bulk_in && usb_endpoint_is_bulk_in(ep) &&
-		    ep->bEndpointAddress == KVASER_USB_HYDRA_BULK_EP_IN_ADDR)
-			dev->bulk_in = ep;
-
-		if (!dev->bulk_out && usb_endpoint_is_bulk_out(ep) &&
-		    ep->bEndpointAddress == KVASER_USB_HYDRA_BULK_EP_OUT_ADDR)
-			dev->bulk_out = ep;
-
-		if (dev->bulk_in && dev->bulk_out)
-			return 0;
-	}
-
-	return -ENODEV;
-}
-
 static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev)
 {
 	int err;
@@ -2120,27 +2168,61 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,
 	spin_lock_irqsave(usb_rx_leftover_lock, irq_flags);
 	usb_rx_leftover_len = card_data->usb_rx_leftover_len;
 	if (usb_rx_leftover_len) {
+		const size_t cmd_size_field_end = offsetof(struct kvaser_cmd_ext, cmd_no_ext);
 		int remaining_bytes;
+		int err;
 
 		cmd = (struct kvaser_cmd *)card_data->usb_rx_leftover;
 
-		cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+		if (cmd->header.cmd_no == CMD_EXTENDED &&
+		    usb_rx_leftover_len < cmd_size_field_end) {
+			remaining_bytes = min_t(int, len, cmd_size_field_end - usb_rx_leftover_len);
+
+			memcpy(card_data->usb_rx_leftover + usb_rx_leftover_len, buf,
+			       remaining_bytes);
+			usb_rx_leftover_len += remaining_bytes;
+			card_data->usb_rx_leftover_len = usb_rx_leftover_len;
+			pos += remaining_bytes;
+
+			if (usb_rx_leftover_len < cmd_size_field_end) {
+				spin_unlock_irqrestore(usb_rx_leftover_lock,
+						       irq_flags);
+				return;
+			}
+		}
 
-		remaining_bytes = min_t(unsigned int, len,
+		err = kvaser_usb_hydra_cmd_size_rx(cmd, usb_rx_leftover_len,
+						   &cmd_len);
+		if (err || cmd_len < usb_rx_leftover_len) {
+			dev_err(&dev->intf->dev, "Format error\n");
+			card_data->usb_rx_leftover_len = 0;
+			spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
+			return;
+		}
+
+		remaining_bytes = min_t(unsigned int, len - pos,
 					cmd_len - usb_rx_leftover_len);
 		/* Make sure we do not overflow usb_rx_leftover */
 		if (remaining_bytes + usb_rx_leftover_len >
 						KVASER_USB_HYDRA_MAX_CMD_LEN) {
 			dev_err(&dev->intf->dev, "Format error\n");
+			card_data->usb_rx_leftover_len = 0;
 			spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
 			return;
 		}
 
-		memcpy(card_data->usb_rx_leftover + usb_rx_leftover_len, buf,
+		memcpy(card_data->usb_rx_leftover + usb_rx_leftover_len, buf + pos,
 		       remaining_bytes);
 		pos += remaining_bytes;
 
 		if (remaining_bytes + usb_rx_leftover_len == cmd_len) {
+			if (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {
+				dev_err(&dev->intf->dev, "Format error\n");
+				card_data->usb_rx_leftover_len = 0;
+				spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
+				return;
+			}
+
 			kvaser_usb_hydra_handle_cmd(dev, cmd);
 			usb_rx_leftover_len = 0;
 		} else {
@@ -2152,11 +2234,17 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,
 	spin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);
 
 	while (pos < len) {
+		int err;
+
 		cmd = buf + pos;
 
-		cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+		err = kvaser_usb_hydra_cmd_size_rx(cmd, len - pos, &cmd_len);
+		if (err && err != -EAGAIN) {
+			dev_err(&dev->intf->dev, "Format error\n");
+			return;
+		}
 
-		if (pos + cmd_len > len) {
+		if (err == -EAGAIN || pos + cmd_len > len) {
 			/* We got first part of a command */
 			int leftover_bytes;
 
@@ -2174,6 +2262,11 @@ static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,
 			break;
 		}
 
+		if (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {
+			dev_err(&dev->intf->dev, "Format error\n");
+			return;
+		}
+
 		kvaser_usb_hydra_handle_cmd(dev, cmd);
 		pos += cmd_len;
 	}
@@ -2203,7 +2296,6 @@ const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = {
 	.dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming,
 	.dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams,
 	.dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter,
-	.dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints,
 	.dev_init_card = kvaser_usb_hydra_init_card,
 	.dev_init_channel = kvaser_usb_hydra_init_channel,
 	.dev_get_software_info = kvaser_usb_hydra_get_software_info,
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index a876c7819b81c..00302b5c6223e 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -1964,22 +1964,6 @@ static int kvaser_usb_leaf_get_berr_counter(const struct net_device *netdev,
 	return 0;
 }
 
-static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
-{
-	struct usb_host_interface *iface_desc;
-	int ret;
-
-	iface_desc = dev->intf->cur_altsetting;
-
-	/* use first bulk endpoint for in and out */
-	ret = usb_find_common_endpoints(iface_desc, &dev->bulk_in, &dev->bulk_out,
-					NULL, NULL);
-	if (ret)
-		return -ENODEV;
-
-	return 0;
-}
-
 const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
 	.dev_set_mode = kvaser_usb_leaf_set_mode,
 	.dev_set_bittiming = kvaser_usb_leaf_set_bittiming,
@@ -1987,7 +1971,6 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
 	.dev_set_data_bittiming = NULL,
 	.dev_get_data_busparams = NULL,
 	.dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter,
-	.dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints,
 	.dev_init_card = kvaser_usb_leaf_init_card,
 	.dev_init_channel = kvaser_usb_leaf_init_channel,
 	.dev_remove_channel = kvaser_usb_leaf_remove_channel,
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index f72e0644c5fdb..6b088a05a901e 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -61,7 +61,7 @@
  *    the following way:
  *
  *	m[n].len <=> the length if message n(including the header in bytes)
- *	m[n] is is aligned to a 4 byte boundary, hence
+ *	m[n] is aligned to a 4 byte boundary, hence
  *	  offset(m[0])	 := 0;
  *	  offset(m[n+1]) := offset(m[n]) + (m[n].len + 3) & 3
  *
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 43d7f22820b88..52661e0882054 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -157,6 +157,7 @@ enum xcan_reg {
 #define XCAN_2_FSR_RI_MASK		0x0000003F /* RX Read Index */
 #define XCAN_DLCR_EDL_MASK		0x08000000 /* EDL Mask in DLC */
 #define XCAN_DLCR_BRS_MASK		0x04000000 /* BRS Mask in DLC */
+#define XCAN_DLCR_ESI_MASK		0x02000000 /* ESI Mask in DLC */
 #define XCAN_ECC_CFG_REECRX_MASK	BIT(2) /* Reset RX FIFO ECC error counters */
 #define XCAN_ECC_CFG_REECTXOL_MASK	BIT(1) /* Reset TXOL FIFO ECC error counters */
 #define XCAN_ECC_CFG_REECTXTL_MASK	BIT(0) /* Reset TXTL FIFO ECC error counters */
@@ -959,6 +960,11 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base)
 
 	/* Check the frame received is FD or not*/
 	if (dlc & XCAN_DLCR_EDL_MASK) {
+		if (dlc & XCAN_DLCR_BRS_MASK)
+			cf->flags |= CANFD_BRS;
+		if (dlc & XCAN_DLCR_ESI_MASK)
+			cf->flags |= CANFD_ESI;
+
 		for (i = 0; i < cf->len; i += 4) {
 			dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) +
 					(dwindex * XCANFD_DW_BYTES);
diff --git a/include/linux/can/core.h b/include/linux/can/core.h
index 2de74c2b78b6c..effb5c31ef401 100644
--- a/include/linux/can/core.h
+++ b/include/linux/can/core.h
@@ -51,7 +51,7 @@ extern void can_proto_unregister(const struct can_proto *cp);
 int can_rx_register(struct net *net, struct net_device *dev,
 		    canid_t can_id, canid_t mask,
 		    void (*func)(struct sk_buff *, void *),
-		    void *data, char *ident, struct sock *sk);
+		    void *data, u64 ino, struct sock *sk);
 
 extern void can_rx_unregister(struct net *net, struct net_device *dev,
 			      canid_t can_id, canid_t mask,
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 6d0710d6f571d..346faddee02eb 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -176,7 +176,7 @@ static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *s
 	return can_dropped_invalid_skb(dev, skb);
 
 invalid_skb:
-	kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 	dev->stats.tx_dropped++;
 	return true;
 }
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 5d27843862fca..87ace09c0d8bd 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -78,12 +78,12 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
 
 	nskb = skb_clone(skb, GFP_ATOMIC);
 	if (unlikely(!nskb)) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return NULL;
 	}
 
 	can_skb_set_owner(nskb, skb->sk);
-	consume_skb(skb);
+	dev_consume_skb_any(skb);
 	return nskb;
 }
 
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 34fe3b28d576f..d97f85fc3232d 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -226,7 +226,7 @@ int can_send(struct sk_buff *skb, int loop)
 		goto inval_skb;
 	}
 
-	if (unlikely(skb->dev->type != ARPHRD_CAN)) {
+	if (unlikely(!can_get_ml_priv(skb->dev))) {
 		err = -EPERM;
 		goto inval_skb;
 	}
@@ -418,7 +418,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  * @mask: CAN mask (see description)
  * @func: callback function on filter match
  * @data: returned parameter for callback function
- * @ident: string for calling module identification
+ * @ino: inode number of sock (0 = unknown)
  * @sk: socket pointer (might be NULL)
  *
  * Description:
@@ -443,7 +443,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  */
 int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 		    canid_t mask, void (*func)(struct sk_buff *, void *),
-		    void *data, char *ident, struct sock *sk)
+		    void *data, u64 ino, struct sock *sk)
 {
 	struct receiver *rcv;
 	struct hlist_head *rcv_list;
@@ -452,7 +452,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 
 	/* insert new receiver  (dev,canid,mask) -> (func,data) */
 
-	if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev)))
+	if (dev && !can_get_ml_priv(dev))
 		return -ENODEV;
 
 	if (dev && !net_eq(net, dev_net(dev)))
@@ -472,7 +472,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 	atomic_long_set(&rcv->matches, 0);
 	rcv->func = func;
 	rcv->data = data;
-	rcv->ident = ident;
+	rcv->ino = ino;
 	rcv->sk = sk;
 
 	hlist_add_head_rcu(&rcv->list, rcv_list);
@@ -519,7 +519,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
 	struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats;
 	struct can_dev_rcv_lists *dev_rcv_lists;
 
-	if (dev && dev->type != ARPHRD_CAN)
+	if (dev && !can_get_ml_priv(dev))
 		return;
 
 	if (dev && !net_eq(net, dev_net(dev)))
@@ -684,8 +684,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct can_skb_ext *csx = can_skb_ext_find(skb);
 
-	if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
-		     !csx || !can_is_can_skb(skb))) {
+	if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_can_skb(skb))) {
 		pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n",
 			     dev->type, skb->len);
 
@@ -710,8 +709,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct can_skb_ext *csx = can_skb_ext_find(skb);
 
-	if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
-		     !csx || !can_is_canfd_skb(skb))) {
+	if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canfd_skb(skb))) {
 		pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n",
 			     dev->type, skb->len);
 
@@ -736,8 +734,7 @@ static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
 {
 	struct can_skb_ext *csx = can_skb_ext_find(skb);
 
-	if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) ||
-		     !csx || !can_is_canxl_skb(skb))) {
+	if (unlikely(!can_get_ml_priv(dev) || !csx || !can_is_canxl_skb(skb))) {
 		pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
 			     dev->type, skb->len);
 
diff --git a/net/can/af_can.h b/net/can/af_can.h
index 87887014f5628..6e593ed5db5f0 100644
--- a/net/can/af_can.h
+++ b/net/can/af_can.h
@@ -55,7 +55,7 @@ struct receiver {
 	atomic_long_t matches;
 	void (*func)(struct sk_buff *skb, void *data);
 	void *data;
-	char *ident;
+	u64 ino;
 	struct sock *sk;
 	struct rcu_head rcu;
 };
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 3d637a1e0ac1a..301920011a300 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -54,6 +54,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/can.h>
+#include <linux/can/can-ml.h>
 #include <linux/can/core.h>
 #include <linux/can/skb.h>
 #include <linux/can/bcm.h>
@@ -220,9 +221,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 	struct bcm_sock *bo = bcm_sk(sk);
 	struct bcm_op *op;
 
-	seq_printf(m, ">>> socket %pK", sk->sk_socket);
-	seq_printf(m, " / sk %pK", sk);
-	seq_printf(m, " / bo %pK", bo);
+	seq_printf(m, ">>> sock inode %s", bo->procname);
 	seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
 	seq_printf(m, " / bound %s", bcm_proc_getifname(net, ifname, bo->ifindex));
 	seq_printf(m, " <<<\n");
@@ -1536,7 +1535,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 						      op->can_id,
 						      REGMASK(op->can_id),
 						      bcm_rx_handler, op,
-						      "bcm", sk);
+						      sock_i_ino(sk), sk);
 
 				/* keep a tracked reference so that a later
 				 * unregister can safely reach the device even
@@ -1560,7 +1559,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 		} else {
 			err = can_rx_register(sock_net(sk), NULL, op->can_id,
 					      REGMASK(op->can_id),
-					      bcm_rx_handler, op, "bcm", sk);
+					      bcm_rx_handler, op,
+					      sock_i_ino(sk), sk);
 		}
 
 		if (err) {
@@ -1719,7 +1719,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 				goto out_release;
 			}
 
-			if (dev->type != ARPHRD_CAN) {
+			if (!can_get_ml_priv(dev)) {
 				dev_put(dev);
 				ret = -ENODEV;
 				goto out_release;
@@ -1867,7 +1867,7 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
 		return NOTIFY_DONE;
@@ -1926,21 +1926,19 @@ static int bcm_release(struct socket *sock)
 
 	/* remove bcm_ops, timer, rx_unregister(), etc. */
 
-	spin_lock(&bcm_notifier_lock);
-	while (bcm_busy_notifier == bo) {
-		spin_unlock(&bcm_notifier_lock);
-		schedule_timeout_uninterruptible(1);
-		spin_lock(&bcm_notifier_lock);
-	}
-	list_del(&bo->notifier);
-	spin_unlock(&bcm_notifier_lock);
-
+	/* Remove the procfs entry and the tx_ops before taking RTNL:
+	 * remove_proc_entry() waits for concurrent readers of the entry and
+	 * must not hold up RTNL for them. Clear bo->bcm_proc_read so that
+	 * bcm_notify() does not remove the entry a second time.
+	 */
 	lock_sock(sk);
 
 #if IS_ENABLED(CONFIG_PROC_FS)
 	/* remove procfs entry */
-	if (net->can.bcmproc_dir && bo->bcm_proc_read)
+	if (net->can.bcmproc_dir && bo->bcm_proc_read) {
 		remove_proc_entry(bo->procname, net->can.bcmproc_dir);
+		bo->bcm_proc_read = NULL;
+	}
 #endif /* CONFIG_PROC_FS */
 
 	list_for_each_entry_safe(op, next, &bo->tx_ops, list) {
@@ -1948,6 +1946,21 @@ static int bcm_release(struct socket *sock)
 		bcm_remove_op(op);
 	}
 
+	release_sock(sk);
+
+	rtnl_lock();
+
+	/* The netdev notifier chain runs under RTNL, so bcm_notifier() can't
+	 * be walking bcm_notifier_list and point to this socket. The spinlock
+	 * is still needed as bcm_init() adds sockets without holding RTNL.
+	 */
+	spin_lock(&bcm_notifier_lock);
+	WARN_ON_ONCE(bcm_busy_notifier == bo);
+	list_del(&bo->notifier);
+	spin_unlock(&bcm_notifier_lock);
+
+	lock_sock(sk);
+
 	list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
 		/*
 		 * Don't care if we're bound or not (due to netdev problems)
@@ -1973,6 +1986,8 @@ static int bcm_release(struct socket *sock)
 
 	}
 
+	rtnl_unlock();
+
 	synchronize_rcu();
 
 	list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
@@ -2024,7 +2039,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
 			ret = -ENODEV;
 			goto fail;
 		}
-		if (dev->type != ARPHRD_CAN) {
+		if (!can_get_ml_priv(dev)) {
 			dev_put(dev);
 			ret = -ENODEV;
 			goto fail;
@@ -2040,8 +2055,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
 
 #if IS_ENABLED(CONFIG_PROC_FS)
 	if (net->can.bcmproc_dir) {
-		/* unique socket address as filename */
-		sprintf(bo->procname, "%llu", sock_i_ino(sk));
+		/* use unique socket inode number as filename */
+		snprintf(bo->procname, sizeof(bo->procname),
+			 "%llu", sock_i_ino(sk));
 		bo->bcm_proc_read = proc_create_net_single(bo->procname, 0644,
 						     net->can.bcmproc_dir,
 						     bcm_proc_show, sk);
diff --git a/net/can/gw.c b/net/can/gw.c
index 5793cb2420ed3..8a5327d8a00e8 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -52,6 +52,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/can.h>
+#include <linux/can/can-ml.h>
 #include <linux/can/core.h>
 #include <linux/can/skb.h>
 #include <linux/can/gw.h>
@@ -579,7 +580,7 @@ static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
 {
 	return can_rx_register(net, gwj->src.dev, gwj->ccgw.filter.can_id,
 			       gwj->ccgw.filter.can_mask, can_can_gw_rcv,
-			       gwj, "gw", NULL);
+			       gwj, 0, NULL);
 }
 
 static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)
@@ -612,7 +613,7 @@ static int cgw_notifier(struct notifier_block *nb,
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct net *net = dev_net(dev);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 
 	if (msg == NETDEV_UNREGISTER) {
@@ -1163,7 +1164,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
 	if (!gwj->src.dev)
 		goto out;
 
-	if (gwj->src.dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(gwj->src.dev))
 		goto out;
 
 	gwj->dst.dev = __dev_get_by_index(net, gwj->ccgw.dst_idx);
@@ -1171,7 +1172,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
 	if (!gwj->dst.dev)
 		goto out;
 
-	if (gwj->dst.dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(gwj->dst.dev))
 		goto out;
 
 	/* is sending the skb back to the incoming interface intended? */
diff --git a/net/can/isotp.c b/net/can/isotp.c
index f5dc9d04bd686..17ff40a4708db 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -65,6 +65,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <linux/can.h>
+#include <linux/can/can-ml.h>
 #include <linux/can/core.h>
 #include <linux/can/skb.h>
 #include <linux/can/isotp.h>
@@ -755,6 +756,14 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
 	if (skb->len != so->ll.mtu)
 		return;
 
+	/* check for correct CAN CC/FD frame content */
+	if (so->ll.mtu == CAN_MTU) {
+		if (!can_is_can_skb(skb))
+			return;
+	} else if (!can_is_canfd_skb(skb)) {
+		return;
+	}
+
 	cf = (struct canfd_frame *)skb->data;
 
 	/* if enabled: check reception of my configured extended address */
@@ -1479,16 +1488,17 @@ static int isotp_release(struct socket *sock)
 	/* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */
 	wake_up_interruptible(&so->wait);
 
+	rtnl_lock();
+
+	/* The netdev notifier chain runs under RTNL, so isotp_notifier() can't
+	 * be walking isotp_notifier_list and point to this socket. The spinlock
+	 * is still needed as isotp_init() adds sockets without holding RTNL.
+	 */
 	spin_lock(&isotp_notifier_lock);
-	while (isotp_busy_notifier == so) {
-		spin_unlock(&isotp_notifier_lock);
-		schedule_timeout_uninterruptible(1);
-		spin_lock(&isotp_notifier_lock);
-	}
+	WARN_ON_ONCE(isotp_busy_notifier == so);
 	list_del(&so->notifier);
 	spin_unlock(&isotp_notifier_lock);
 
-	rtnl_lock();
 	lock_sock(sk);
 
 	/* remove current filters & unregister
@@ -1496,11 +1506,11 @@ static int isotp_release(struct socket *sock)
 	 */
 	if (so->bound && so->dev) {
 		if (isotp_register_rxid(so))
-			can_rx_unregister(net, so->dev, so->rxid,
+			can_rx_unregister(dev_net(so->dev), so->dev, so->rxid,
 					  SINGLE_MASK(so->rxid),
 					  isotp_rcv, sk);
 
-		can_rx_unregister(net, so->dev, so->txid,
+		can_rx_unregister(dev_net(so->dev), so->dev, so->txid,
 				  SINGLE_MASK(so->txid),
 				  isotp_rcv_echo, sk);
 		netdev_put(so->dev, &so->dev_tracker);
@@ -1610,7 +1620,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
 		err = -ENODEV;
 		goto out;
 	}
-	if (dev->type != ARPHRD_CAN) {
+	if (!can_get_ml_priv(dev)) {
 		err = -ENODEV;
 		goto out_put_dev;
 	}
@@ -1625,14 +1635,14 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l
 
 	if (isotp_register_rxid(so))
 		can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
-				isotp_rcv, sk, "isotp", sk);
+				isotp_rcv, sk, sock_i_ino(sk), sk);
 
 	/* no consecutive frame echo skb in flight */
 	WRITE_ONCE(so->cfecho, 0);
 
 	/* register for echo skb's */
 	can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
-			isotp_rcv_echo, sk, "isotpe", sk);
+			isotp_rcv_echo, sk, sock_i_ino(sk), sk);
 
 	/* switch to new settings */
 	so->ifindex = ifindex;
@@ -1897,7 +1907,7 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
 		return NOTIFY_DONE;
diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
index 5e5e6c228f225..d9384cf0e356f 100644
--- a/net/can/j1939/main.c
+++ b/net/can/j1939/main.c
@@ -184,7 +184,7 @@ static int j1939_can_rx_register(struct j1939_priv *priv)
 
 	j1939_priv_get(priv);
 	ret = can_rx_register(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
-			      j1939_can_recv, priv, "j1939", NULL);
+			      j1939_can_recv, priv, 0, NULL);
 	if (ret < 0) {
 		j1939_priv_put(priv);
 		return ret;
diff --git a/net/can/proc.c b/net/can/proc.c
index de4d05ae34597..64994ab485414 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -76,16 +76,39 @@ static const char rx_list_name[][8] = {
  * af_can statistics stuff
  */
 
+static void can_reset_pkg_stats(struct can_pkg_stats *pkg_stats)
+{
+	atomic_long_set(&pkg_stats->rx_frames, 0);
+	atomic_long_set(&pkg_stats->tx_frames, 0);
+	atomic_long_set(&pkg_stats->matches, 0);
+
+	pkg_stats->total_rx_rate = 0;
+	pkg_stats->total_tx_rate = 0;
+	pkg_stats->total_rx_match_ratio = 0;
+
+	pkg_stats->current_rx_rate = 0;
+	pkg_stats->current_tx_rate = 0;
+	pkg_stats->current_rx_match_ratio = 0;
+
+	pkg_stats->max_rx_rate = 0;
+	pkg_stats->max_tx_rate = 0;
+	pkg_stats->max_rx_match_ratio = 0;
+
+	atomic_long_set(&pkg_stats->rx_frames_delta, 0);
+	atomic_long_set(&pkg_stats->tx_frames_delta, 0);
+	atomic_long_set(&pkg_stats->matches_delta, 0);
+}
+
 static void can_init_stats(struct net *net)
 {
 	struct can_pkg_stats *pkg_stats = net->can.pkg_stats;
 	struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats;
 	/*
-	 * This memset function is called from a timer context (when
+	 * This stats reset is called from a timer context (when
 	 * can_stattimer is active which is the default) OR in a process
 	 * context (reading the proc_fs when can_stattimer is disabled).
 	 */
-	memset(pkg_stats, 0, sizeof(struct can_pkg_stats));
+	can_reset_pkg_stats(pkg_stats);
 	pkg_stats->jiffies_init = jiffies;
 
 	rcv_lists_stats->stats_reset++;
@@ -192,25 +215,27 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
 
 	hlist_for_each_entry_rcu(r, rx_list, list) {
 		char *fmt = (r->can_id & CAN_EFF_FLAG)?
-			"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\n" :
-			"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\n";
+			"  %6s  %08x  %08x  %8ld  %10llu" :
+			"  %6s     %03x    %08x  %8ld  %10llu";
 
 		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
-			   r->func, r->data, atomic_long_read(&r->matches),
-			   r->ident);
+			   atomic_long_read(&r->matches), r->ino);
+
+		/* without kallsyms %ps would print the raw text address */
+		if (IS_ENABLED(CONFIG_KALLSYMS))
+			seq_printf(m, "  %ps\n", r->func);
+		else
+			seq_puts(m, "  (unknown)\n");
 	}
 }
 
 static void can_print_recv_banner(struct seq_file *m)
 {
 	/*
-	 *                  can1.  00000000  00000000  00000000
-	 *                 .......          0  tp20
+	 *    device   can_id   can_mask   matches  sock_inode  function
+	 *     vcan0     000    00000000         0       43798  raw_rcv [can_raw]
 	 */
-	if (IS_ENABLED(CONFIG_64BIT))
-		seq_puts(m, "  device   can_id   can_mask      function          userdata       matches  ident\n");
-	else
-		seq_puts(m, "  device   can_id   can_mask  function  userdata   matches  ident\n");
+	seq_puts(m, "  device   can_id   can_mask   matches  sock_inode  function\n");
 }
 
 static int can_stats_proc_show(struct seq_file *m, void *v)
diff --git a/net/can/raw.c b/net/can/raw.c
index 0acd4f6c6dd67..d95ce54a4c458 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -226,7 +226,7 @@ static int raw_enable_filters(struct net *net, struct net_device *dev,
 	for (i = 0; i < count; i++) {
 		err = can_rx_register(net, dev, filter[i].can_id,
 				      filter[i].can_mask,
-				      raw_rcv, sk, "raw", sk);
+				      raw_rcv, sk, sock_i_ino(sk), sk);
 		if (err) {
 			/* clean up successfully registered filters */
 			while (--i >= 0)
@@ -247,7 +247,7 @@ static int raw_enable_errfilter(struct net *net, struct net_device *dev,
 
 	if (err_mask)
 		err = can_rx_register(net, dev, 0, err_mask | CAN_ERR_FLAG,
-				      raw_rcv, sk, "raw", sk);
+				      raw_rcv, sk, sock_i_ino(sk), sk);
 
 	return err;
 }
@@ -348,7 +348,7 @@ static int raw_notifier(struct notifier_block *nb, unsigned long msg,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (dev->type != ARPHRD_CAN)
+	if (!can_get_ml_priv(dev))
 		return NOTIFY_DONE;
 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
 		return NOTIFY_DONE;
@@ -422,16 +422,17 @@ static int raw_release(struct socket *sock)
 	ro = raw_sk(sk);
 	net = sock_net(sk);
 
+	rtnl_lock();
+
+	/* The netdev notifier chain runs under RTNL, so raw_notifier() can't
+	 * be walking raw_notifier_list and point to this socket. The spinlock
+	 * is still needed as raw_init() adds sockets without holding RTNL.
+	 */
 	spin_lock(&raw_notifier_lock);
-	while (raw_busy_notifier == ro) {
-		spin_unlock(&raw_notifier_lock);
-		schedule_timeout_uninterruptible(1);
-		spin_lock(&raw_notifier_lock);
-	}
+	WARN_ON_ONCE(raw_busy_notifier == ro);
 	list_del(&ro->notifier);
 	spin_unlock(&raw_notifier_lock);
 
-	rtnl_lock();
 	lock_sock(sk);
 
 	/* remove current filters & unregister */
@@ -491,7 +492,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
 			err = -ENODEV;
 			goto out;
 		}
-		if (dev->type != ARPHRD_CAN) {
+		if (!can_get_ml_priv(dev)) {
 			err = -ENODEV;
 			goto out_put_dev;
 		}
@@ -529,8 +530,7 @@ static int raw_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int len
 		ro->bound = 1;
 		/* bind() ok -> hold a reference for new ro->dev */
 		ro->dev = dev;
-		if (ro->dev)
-			netdev_hold(ro->dev, &ro->dev_tracker, GFP_KERNEL);
+		netdev_hold(ro->dev, &ro->dev_tracker, GFP_KERNEL);
 	}
 
 out_put_dev:

47/3 2026/10/15 04:36 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 61078
							output: 40
							thoughts: 2232
						

Thoughts:
**KMSAN Fuzzing Session Assessment for CAN Subsystem Patches**

Okay, let's dive into this patch series and determine if it warrants a dedicated KMSAN fuzzing session. My focus is laser-sharp: does it introduce or modify any code paths that could lead to *uninitialized memory reads* that KASAN, LOCKDEP, or other standard bug detectors would miss? That's the critical question. I'm not worried about out-of-bounds accesses, UAFs, or deadlocks – KASAN's got that. My goal is to only request the expensive KMSAN session if it's truly *necessary* to catch memory leaks that would otherwise go unnoticed.

Looking through the patches, I see a lot of activity: DT binding updates, documentation changes, driver removals (good hygiene), and PM ops cleanups. Those are unlikely to introduce uninitialized memory issues.

Several patches focus on CAN controller drivers and their initialization and cleanup: `cc770`, `ctucanfd`, `flexcan`, `m_can`, `rcar_canfd`, `spi/hi311x`, `spi/mcp251x`, and `sun4i_can`. I'll have to pay attention to any memory allocation or struct initialization in these, but generally, I expect the established patterns to be sound. I'll need to check how the removal of the old Softing driver is handled, just in case there was some memory management assumed.

The `dev/skb.c` patch replacing `kfree_skb()` with `dev_kfree_skb_any()` and adding a CANXL check is generally a good thing, but I'll make sure there's no subtle data handling changes in the updated logic.

I'm particularly interested in `esdacc.c`, where there are write order changes to the FIFO. Ordering issues can be tricky; I want to ensure the reordered writes don't introduce a window where uninitialized data could leak.

The USB driver updates (`kvaser_usb`, `ucan`, `ems_usb`) have security implications because of USB commands. The bounds checks and validation on RX commands in the Kvaser USB code are very good, but I'll need to confirm that any new data structures or code paths are properly initialized.

The `xilinx_can.c` patch setting `CANFD_BRS` and `CANFD_ESI` looks fairly straightforward, but I'll want to make sure the DLC bit handling is safe.

The changes in `net/can/af_can.c`, `bcm.c`, `gw.c`, `isotp.c`, `proc.c`, and `raw.c` and associated header files are the most concerning. They modify the CAN receiver registration, including a change from `ident` (a string) to `ino` (a `u64`). I need to be *absolutely* certain that this change doesn't introduce a vulnerability, especially in how `ino` is used. The replacement of kernel pointers in proc output with `ino` is generally a good security practice (less information leakage), but the use of `sock_i_ino` warrants careful review. The new CAN receiver registration logic, and locking fixes, are all areas I'll need to check to make sure no new uninitialized memory issues have been exposed.

I need to circle back to `net/can/proc.c` and specifically `can_reset_pkg_stats`. I need to confirm that it's safe to replace `memset` with that function. *What exactly* is in `struct can_pkg_stats`? I'll need to check the definition to be sure. I'll grep to confirm. If that function doesn't properly zero all the fields, that could be a significant KMSAN issue, leading to a potential information leak.



48/3 2026/10/15 04:36 tool grepper
0m Args:
{
  "Expression": "struct can_pkg_stats",
  "PathPrefixes": [
    "net/can/",
    "include/linux/can/"
  ]
}

Results:
{
  "Output": "net/can/af_can.c=202=int can_send(struct sk_buff *skb, int loop)\n--\nnet/can/af_can.c-204-\tstruct sk_buff *newskb = NULL;\nnet/can/af_can.c:205:\tstruct can_pkg_stats *pkg_stats = dev_net(skb-\u003edev)-\u003ecan.pkg_stats;\nnet/can/af_can.c-206-\tint err = -EINVAL;\n--\nnet/can/af_can.c=651=static void can_receive(struct sk_buff *skb, struct net_device *dev)\n--\nnet/can/af_can.c-654-\tstruct net *net = dev_net(dev);\nnet/can/af_can.c:655:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/af_can.c-656-\tint matches;\n--\nnet/can/af_can.h=51=struct receiver {\n--\nnet/can/af_can.h-65-/* can be reset e.g. by can_init_stats() */\nnet/can/af_can.h:66:struct can_pkg_stats {\nnet/can/af_can.h-67-\tunsigned long jiffies_init;\n--\nnet/can/proc.c=68=static const char rx_list_name[][8] = {\n--\nnet/can/proc.c-78-\nnet/can/proc.c:79:static void can_reset_pkg_stats(struct can_pkg_stats *pkg_stats)\nnet/can/proc.c-80-{\n--\nnet/can/proc.c=102=static void can_init_stats(struct net *net)\nnet/can/proc.c-103-{\nnet/can/proc.c:104:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-105-\tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\n--\nnet/can/proc.c=138=void can_stat_update(struct timer_list *t)\n--\nnet/can/proc.c-140-\tstruct net *net = timer_container_of(net, t, can.stattimer);\nnet/can/proc.c:141:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-142-\tunsigned long j = jiffies; /* snapshot */\n--\nnet/can/proc.c=241=static int can_stats_proc_show(struct seq_file *m, void *v)\n--\nnet/can/proc.c-243-\tstruct net *net = m-\u003eprivate;\nnet/can/proc.c:244:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-245-\tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\n--\nnet/can/proc.c=306=static int can_reset_stats_proc_show(struct seq_file *m, void *v)\n--\nnet/can/proc.c-309-\tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\nnet/can/proc.c:310:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-311-\n"
}

49/3 2026/10/15 04:36 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 65119
							output: 36
							thoughts: 21
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Diving into `af_can.h` - A Quick Check**

Okay, time to get my bearings. I need a quick refresher on the CAN socket address family, specifically the structures defined in the Linux kernel. Let's start with `net/can/af_can.h`. I'm going to jump to around line 66, because that's usually where the core definitions of the socket address structures start. I want to see how the kernel represents a CAN address. I'm looking for the foundational data structures and flags. No need to go into the weeds just yet, just get a high level overview of the basics. Let's see what we've got.



50/3 2026/10/15 04:36 tool read-file
0m Args:
{
  "File": "net/can/af_can.h",
  "FirstLine": 60,
  "LineCount": 40
}

Results:
{
  "Contents": "  60:\t\tstruct rcu_head rcu;\n  61:\t};\n  62:\t\n  63:\t/* statistic structures */\n  64:\t\n  65:\t/* can be reset e.g. by can_init_stats() */\n  66:\tstruct can_pkg_stats {\n  67:\t\tunsigned long jiffies_init;\n  68:\t\n  69:\t\tatomic_long_t rx_frames;\n  70:\t\tatomic_long_t tx_frames;\n  71:\t\tatomic_long_t matches;\n  72:\t\n  73:\t\tunsigned long total_rx_rate;\n  74:\t\tunsigned long total_tx_rate;\n  75:\t\tunsigned long total_rx_match_ratio;\n  76:\t\n  77:\t\tunsigned long current_rx_rate;\n  78:\t\tunsigned long current_tx_rate;\n  79:\t\tunsigned long current_rx_match_ratio;\n  80:\t\n  81:\t\tunsigned long max_rx_rate;\n  82:\t\tunsigned long max_tx_rate;\n  83:\t\tunsigned long max_rx_match_ratio;\n  84:\t\n  85:\t\tatomic_long_t rx_frames_delta;\n  86:\t\tatomic_long_t tx_frames_delta;\n  87:\t\tatomic_long_t matches_delta;\n  88:\t};\n  89:\t\n  90:\t/* persistent statistics */\n  91:\tstruct can_rcv_lists_stats {\n  92:\t\tunsigned long stats_reset;\n  93:\t\tunsigned long user_reset;\n  94:\t\tunsigned long rcv_entries;\n  95:\t\tunsigned long rcv_entries_max;\n  96:\t};\n  97:\t\n  98:\t/* function prototypes for the CAN networklayer procfs (proc.c) */\n  99:\tvoid can_init_proc(struct net *net);\n"
}

51/3 2026/10/15 04:36 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 65843
							output: 29
							thoughts: 97
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating the Package Statistics Reset**

Right, so `can_reset_pkg_stats` is the function we're looking at. The key here is what *doesn't* get reset. It leaves `jiffies_init` untouched, setting it right after, so that tells me the timestamp is critical and reflects when the statistics are being initialized. Okay, I get it.

Now, where is `pkg_stats` actually allocated? Since it's being zeroed, it’s most likely done by `kzalloc`. I need to track down the initialization to fully grasp its lifecycle. It's either in `can_init_proc` or `can_pernet_init`. Given the nature of CAN, I'm leaning toward `can_pernet_init`. Let me quickly confirm by checking those allocation points, that should provide the context I need. I'll focus on `can_pernet_init` since it's the more likely location. I'm guessing that will shed light on what these package statistics are measuring.



52/3 2026/10/15 04:36 tool grepper
0m Args:
{
  "Expression": "pkg_stats =",
  "PathPrefixes": [
    "net/can/"
  ]
}

Results:
{
  "Output": "net/can/af_can.c=202=int can_send(struct sk_buff *skb, int loop)\n--\nnet/can/af_can.c-204-\tstruct sk_buff *newskb = NULL;\nnet/can/af_can.c:205:\tstruct can_pkg_stats *pkg_stats = dev_net(skb-\u003edev)-\u003ecan.pkg_stats;\nnet/can/af_can.c-206-\tint err = -EINVAL;\n--\nnet/can/af_can.c=651=static void can_receive(struct sk_buff *skb, struct net_device *dev)\n--\nnet/can/af_can.c-654-\tstruct net *net = dev_net(dev);\nnet/can/af_can.c:655:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/af_can.c-656-\tint matches;\n--\nnet/can/af_can.c=820=static int can_pernet_init(struct net *net)\n--\nnet/can/af_can.c-825-\t\tgoto out;\nnet/can/af_can.c:826:\tnet-\u003ecan.pkg_stats = kzalloc_obj(*net-\u003ecan.pkg_stats);\nnet/can/af_can.c-827-\tif (!net-\u003ecan.pkg_stats)\n--\nnet/can/proc.c=102=static void can_init_stats(struct net *net)\nnet/can/proc.c-103-{\nnet/can/proc.c:104:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-105-\tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\n--\nnet/can/proc.c=138=void can_stat_update(struct timer_list *t)\n--\nnet/can/proc.c-140-\tstruct net *net = timer_container_of(net, t, can.stattimer);\nnet/can/proc.c:141:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-142-\tunsigned long j = jiffies; /* snapshot */\n--\nnet/can/proc.c=241=static int can_stats_proc_show(struct seq_file *m, void *v)\n--\nnet/can/proc.c-243-\tstruct net *net = m-\u003eprivate;\nnet/can/proc.c:244:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-245-\tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\n--\nnet/can/proc.c=306=static int can_reset_stats_proc_show(struct seq_file *m, void *v)\n--\nnet/can/proc.c-309-\tstruct can_rcv_lists_stats *rcv_lists_stats = net-\u003ecan.rcv_lists_stats;\nnet/can/proc.c:310:\tstruct can_pkg_stats *pkg_stats = net-\u003ecan.pkg_stats;\nnet/can/proc.c-311-\n"
}

53/3 2026/10/15 04:36 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 67090
							output: 37
							thoughts: 84
						

Thoughts:
Okay, here's my breakdown of what's happening, from my perspective, as an embedded systems expert:

**Allocating and Checking Receiver Structures in CAN Driver**

Alright, so the first step in this process confirms a memory allocation. Specifically, `net->can.pkg_stats` is being zeroed and allocated using `kzalloc_obj()`.  That looks standard – we're getting a fresh object for our CAN statistics. Good, good. Now, I need to dig into the receiver setup. I'm focusing on that `can_rx_register` function. My next thought is to examine how the receiver struct, or `rcv`, is being set up. I see that `rcv = kmem_cache_alloc(rcv_cache, GFP_KERNEL)` is being used to allocate the `rcv` structure. The next piece of code I'll need to look at is precisely how this `rcv` is initialized within that `can_rx_register` function, to make sure there are no surprises with the memory.



54/3 2026/10/15 04:37 tool read-file
0m Args:
{
  "File": "net/can/af_can.c",
  "FirstLine": 460,
  "LineCount": 35
}

Results:
{
  "Contents": " 460:\t\n 461:\t\trcv = kmem_cache_alloc(rcv_cache, GFP_KERNEL);\n 462:\t\tif (!rcv)\n 463:\t\t\treturn -ENOMEM;\n 464:\t\n 465:\t\tspin_lock_bh(\u0026net-\u003ecan.rcvlists_lock);\n 466:\t\n 467:\t\tdev_rcv_lists = can_dev_rcv_lists_find(net, dev);\n 468:\t\trcv_list = can_rcv_list_find(\u0026can_id, \u0026mask, dev_rcv_lists);\n 469:\t\n 470:\t\trcv-\u003ecan_id = can_id;\n 471:\t\trcv-\u003emask = mask;\n 472:\t\tatomic_long_set(\u0026rcv-\u003ematches, 0);\n 473:\t\trcv-\u003efunc = func;\n 474:\t\trcv-\u003edata = data;\n 475:\t\trcv-\u003eino = ino;\n 476:\t\trcv-\u003esk = sk;\n 477:\t\n 478:\t\thlist_add_head_rcu(\u0026rcv-\u003elist, rcv_list);\n 479:\t\tdev_rcv_lists-\u003eentries++;\n 480:\t\n 481:\t\trcv_lists_stats-\u003ercv_entries++;\n 482:\t\trcv_lists_stats-\u003ercv_entries_max = max(rcv_lists_stats-\u003ercv_entries_max,\n 483:\t\t\t\t\t\t       rcv_lists_stats-\u003ercv_entries);\n 484:\t\tspin_unlock_bh(\u0026net-\u003ecan.rcvlists_lock);\n 485:\t\n 486:\t\treturn 0;\n 487:\t}\n 488:\tEXPORT_SYMBOL(can_rx_register);\n 489:\t\n 490:\t/* can_rx_delete_receiver - rcu callback for single receiver entry removal */\n 491:\tstatic void can_rx_delete_receiver(struct rcu_head *rp)\n 492:\t{\n 493:\t\tstruct receiver *rcv = container_of(rp, struct receiver, rcu);\n 494:\t\tstruct sock *sk = rcv-\u003esk;\n"
}

55/3 2026/10/15 04:37 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 68028
							output: 41
							thoughts: 659
						

Thoughts:
**My Analysis of Potential Issues**

Okay, so I'm looking at this code and immediately I see something I like: the `rcv` struct's fields (`can_id`, `mask`, `matches`, `func`, `data`, `ino`, `sk`, `list`) are all explicitly assigned. Good. Also, when they're printed in `can_print_rcvlist`, everything is initialized *before* it's printed. No obvious uninitialized memory reads there. That's a solid start.

Now, let's drill into the drivers and see what's changed. In `cc770/cc770_platform.c`, I spot a fix: `priv->cpu_interface` was being *read* before it was written! That's a classic bug – reading an uninitialized structure field. It was likely zeroed out by `kzalloc` in the `alloc_candev` function, but it's still bad practice. The fix here is simple and correct: set `priv->cpu_interface` before we read it. Good.

Next, I'm onto `kvaser_usb_hydra.c`. Time to dig in and understand what changed. I'm focusing on the bulk callback and command parsing. I'll inspect `kvaser_usb_hydra_cmd_size_rx`, `kvaser_usb_hydra_verify_cmd_size`, and, crucially, `kvaser_usb_hydra_read_bulk_callback`. My main concern is buffer overruns and reading uninitialized memory. Let's make sure that's addressed in the changes. Okay, the callback now validates lengths, which should prevent both problems. And, it appears the data is either coming from the USB URB buffer (`buf`) or `card_data->usb_rx_leftover`. I'll have to investigate how that `card_data->usb_rx_leftover` is allocated and used to confirm there are no memory safety issues.



56/3 2026/10/15 04:37 tool grepper
0m Args:
{
  "Expression": "usb_rx_leftover",
  "PathPrefixes": [
    "drivers/net/can/usb/kvaser_usb/"
  ]
}

Results:
{
  "Output": "drivers/net/can/usb/kvaser_usb/kvaser_usb.h=68=struct kvaser_usb_dev_card_data_hydra {\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb.h-72-\tu16 transid;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb.h:73:\t/* lock for usb_rx_leftover and usb_rx_leftover_len */\ndrivers/net/can/usb/kvaser_usb/kvaser_usb.h:74:\tspinlock_t usb_rx_leftover_lock;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb.h:75:\tu8 usb_rx_leftover[KVASER_USB_HYDRA_MAX_CMD_LEN];\ndrivers/net/can/usb/kvaser_usb/kvaser_usb.h:76:\tu8 usb_rx_leftover_len;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb.h-77-};\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c=1810=static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev)\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-1819-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:1820:\tmemset(card_data-\u003eusb_rx_leftover, 0, KVASER_USB_HYDRA_MAX_CMD_LEN);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:1821:\tcard_data-\u003eusb_rx_leftover_len = 0;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:1822:\tspin_lock_init(\u0026card_data-\u003eusb_rx_leftover_lock);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-1823-\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c=2156=static void kvaser_usb_hydra_read_bulk_callback(struct kvaser_usb *dev,\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2164-\t\t\t\t\t\t\t\u0026dev-\u003ecard_data.hydra;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2165:\tint usb_rx_leftover_len;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2166:\tspinlock_t *usb_rx_leftover_lock = \u0026card_data-\u003eusb_rx_leftover_lock;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2167-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2168:\tspin_lock_irqsave(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2169:\tusb_rx_leftover_len = card_data-\u003eusb_rx_leftover_len;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2170:\tif (usb_rx_leftover_len) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2171-\t\tconst size_t cmd_size_field_end = offsetof(struct kvaser_cmd_ext, cmd_no_ext);\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2174-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2175:\t\tcmd = (struct kvaser_cmd *)card_data-\u003eusb_rx_leftover;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2176-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2177-\t\tif (cmd-\u003eheader.cmd_no == CMD_EXTENDED \u0026\u0026\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2178:\t\t    usb_rx_leftover_len \u003c cmd_size_field_end) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2179:\t\t\tremaining_bytes = min_t(int, len, cmd_size_field_end - usb_rx_leftover_len);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2180-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2181:\t\t\tmemcpy(card_data-\u003eusb_rx_leftover + usb_rx_leftover_len, buf,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2182-\t\t\t       remaining_bytes);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2183:\t\t\tusb_rx_leftover_len += remaining_bytes;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2184:\t\t\tcard_data-\u003eusb_rx_leftover_len = usb_rx_leftover_len;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2185-\t\t\tpos += remaining_bytes;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2186-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2187:\t\t\tif (usb_rx_leftover_len \u003c cmd_size_field_end) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2188:\t\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2189-\t\t\t\t\t\t       irq_flags);\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2193-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2194:\t\terr = kvaser_usb_hydra_cmd_size_rx(cmd, usb_rx_leftover_len,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2195-\t\t\t\t\t\t   \u0026cmd_len);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2196:\t\tif (err || cmd_len \u003c usb_rx_leftover_len) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2197-\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2198:\t\t\tcard_data-\u003eusb_rx_leftover_len = 0;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2199:\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2200-\t\t\treturn;\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2203-\t\tremaining_bytes = min_t(unsigned int, len - pos,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2204:\t\t\t\t\tcmd_len - usb_rx_leftover_len);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2205:\t\t/* Make sure we do not overflow usb_rx_leftover */\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2206:\t\tif (remaining_bytes + usb_rx_leftover_len \u003e\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2207-\t\t\t\t\t\tKVASER_USB_HYDRA_MAX_CMD_LEN) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2208-\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2209:\t\t\tcard_data-\u003eusb_rx_leftover_len = 0;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2210:\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2211-\t\t\treturn;\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2213-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2214:\t\tmemcpy(card_data-\u003eusb_rx_leftover + usb_rx_leftover_len, buf + pos,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2215-\t\t       remaining_bytes);\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2217-\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2218:\t\tif (remaining_bytes + usb_rx_leftover_len == cmd_len) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2219-\t\t\tif (kvaser_usb_hydra_verify_cmd_size(cmd, cmd_len)) {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2220-\t\t\t\tdev_err(\u0026dev-\u003eintf-\u003edev, \"Format error\\n\");\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2221:\t\t\t\tcard_data-\u003eusb_rx_leftover_len = 0;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2222:\t\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2223-\t\t\t\treturn;\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2226-\t\t\tkvaser_usb_hydra_handle_cmd(dev, cmd);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2227:\t\t\tusb_rx_leftover_len = 0;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2228-\t\t} else {\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2229-\t\t\t/* Command still not complete */\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2230:\t\t\tusb_rx_leftover_len += remaining_bytes;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2231-\t\t}\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2232:\t\tcard_data-\u003eusb_rx_leftover_len = usb_rx_leftover_len;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2233-\t}\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2234:\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2235-\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2251-\t\t\tleftover_bytes = len - pos;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2252:\t\t\t/* Make sure we do not overflow usb_rx_leftover */\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2253-\t\t\tif (leftover_bytes \u003e KVASER_USB_HYDRA_MAX_CMD_LEN) {\n--\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2256-\t\t\t}\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2257:\t\t\tspin_lock_irqsave(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2258:\t\t\tmemcpy(card_data-\u003eusb_rx_leftover, buf + pos,\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2259-\t\t\t       leftover_bytes);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2260:\t\t\tcard_data-\u003eusb_rx_leftover_len = leftover_bytes;\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c:2261:\t\t\tspin_unlock_irqrestore(usb_rx_leftover_lock, irq_flags);\ndrivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c-2262-\t\t\tbreak;\n"
}

57/3 2026/10/15 04:37 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 73003
							output: 341
							thoughts: 2013
						

Thoughts:
**KMSAN Assessment of CAN Subsystem Patch Series**

Okay, let's break this down. My goal is to determine if this patch series necessitates a `NeedsKMSAN=true` flag. The KMSAN requirements are clear: it's about identifying *uninitialized memory* risks that KASAN, LOCKDEP, or standard bug detectors would *miss*. This means we're looking for code that introduces or modifies kernel structures sent to userspace with potentially uninitialized fields, logic that depends on uninitialized variables, or allocations where uninitialized fields could be read later.

First, I examined `kvaser_usb_hydra.c`. The size checks in `kvaser_usb_hydra_cmd_size_rx` are *good* – they're specifically *preventing* out-of-bounds reads from uninitialized USB buffers, which is the opposite of the KMSAN concern. In fact, it reinforces the safety of how the buffer is handled by validating the input.

Next, I looked at `xilinx_can.c`. Setting flags on the `cf` structure allocated via `alloc_canfd_skb()` using `|=` is perfectly fine, especially given that `alloc_canfd_skb` zeroes the skb/cf structure. No worries there.

The changes in `bcm.c` are mostly about locking reordering and outputting sock inode numbers to procfs and symbols. The use of `snprintf` is a good practice and the changes are unlikely to introduce uninitialized memory issues.

The `isotp.c` validation of `skb` payload with `can_is_can_skb` and `can_is_canfd_skb` provides more safety and is good, not a KMSAN issue.

The `dev/skb.c` change to use `dev_kfree_skb_any` and `dev_consume_skb_any` are better alternatives for atomic/interrupt contexts, and have nothing to do with uninitialized memory.

Renaming and probe changes in `rcar_canfd.c` are irrelevant to the current task.

Switching to `DEFINE_SIMPLE_DEV_PM_OPS` in various drivers is modernization that doesn't affect KMSAN.

The removal of the `softing` CAN driver doesn't introduce any new risks either.

Now, let's address the KMSAN criteria directly:

1.  **Kernel structures sent to userspace:**  The key areas here are the procfs changes in `proc.c`, `af_can.c`, and `bcm.c`.  I see that `%pK` (pointer hashing) is *gone*, replaced with `sock_i_ino(sk)` (inode number) and `%ps` (function symbol) in procfs output. This does *not* directly expose raw struct memory.  The `can_reset_pkg_stats` cleanly zeroes all statistics fields.  These changes actually *reduce* the risk, not increase it. `xilinx_can.c` has similar behavior: `cf` is part of skb, allocated via `alloc_canfd_skb()` which zeroes `cf`, which is not an issue.
2.  **Conditional logic based on potentially uninitialized variables:** Nothing here.  The code clearly initializes/validates data before use.
3.  **Allocation of complex data structures:** All structures touched are fully initialized or zeroed. The code is safe.
4.  **Bounds checks allowing access to uninitialized bytes:** `kvaser_usb_hydra.c` actually *prevents* this by validating input buffer sizes, mitigating any risk.

Given this analysis, I'm confident that these changes *do not* introduce or expose uninitialized memory risks.  Any potential memory errors are already covered by KASAN, LOCKDEP, or standard kernel debug mechanisms.  Therefore, `NeedsKMSAN=false`. Let's feed this conclusion into the set-results tool.



58/3 2026/10/15 04:37 tool set-results
0m Args:
{
  "KMSANReasoning": "The patch series focuses on the Linux CAN subsystem and includes:\n1. Procfs formatting updates in net/can (replacing pointer formatting %pK with socket inode numbers and %ps symbol lookups, plus introducing can_reset_pkg_stats() to explicitly zero all fields of struct can_pkg_stats).\n2. Socket lifecycle and locking refactoring in BCM, Raw, and ISO-TP sockets (reordering RTNL vs notifier spinlock acquisitions to prevent deadlocks and race conditions).\n3. Packet bounds and length validation in drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c to ensure incoming USB command frames have sufficient bytes before parsing.\n4. Driver maintenance such as PM ops modernization (DEFINE_SIMPLE_DEV_PM_OPS), safe SKB freeing (dev_kfree_skb_any), reference count fixes (of_node_put, clk_put), and removal of the deprecated softing driver.\n5. In cc770_platform.c, fixing a logic bug where priv-\u003ecpu_interface was read before being assigned from platform data.\n\nNone of the changes introduce uninitialized stack or heap memory reads, struct padding leaks, or uninitialized kernel-to-user copy operations. The potential risks associated with these patches (deadlocks, use-after-free, out-of-bounds accesses) are already covered by LOCKDEP and standard KASAN. Therefore, a dedicated KMSAN session is not warranted.",
  "NeedsKMSAN": false
}

Results:
{
  "KMSANReasoning": "The patch series focuses on the Linux CAN subsystem and includes:\n1. Procfs formatting updates in net/can (replacing pointer formatting %pK with socket inode numbers and %ps symbol lookups, plus introducing can_reset_pkg_stats() to explicitly zero all fields of struct can_pkg_stats).\n2. Socket lifecycle and locking refactoring in BCM, Raw, and ISO-TP sockets (reordering RTNL vs notifier spinlock acquisitions to prevent deadlocks and race conditions).\n3. Packet bounds and length validation in drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c to ensure incoming USB command frames have sufficient bytes before parsing.\n4. Driver maintenance such as PM ops modernization (DEFINE_SIMPLE_DEV_PM_OPS), safe SKB freeing (dev_kfree_skb_any), reference count fixes (of_node_put, clk_put), and removal of the deprecated softing driver.\n5. In cc770_platform.c, fixing a logic bug where priv-\u003ecpu_interface was read before being assigned from platform data.\n\nNone of the changes introduce uninitialized stack or heap memory reads, struct padding leaks, or uninitialized kernel-to-user copy operations. The potential risks associated with these patches (deadlocks, use-after-free, out-of-bounds accesses) are already covered by LOCKDEP and standard KASAN. Therefore, a dedicated KMSAN session is not warranted.",
  "NeedsKMSAN": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)