can: add arasan canfd controller support
Subsystems (2)
cover can: add arasan canfd controller support
This series add arasan canfd controller support.
patch1 documents the dt-bindings for arasan canfd controller patch2 adds the driver for the arasan canfd controller
Jisheng Zhang (2):
dt-bindings: can: add arasan canfd controller
can: arasan-canfd: add driver for arasan CAN-FD controller
.../bindings/net/can/arasan,canfd.yaml | 63 + drivers/net/can/Kconfig | 6 + drivers/net/can/Makefile | 1 + drivers/net/can/arasan-canfd.c | 1057 +++++++++++++++++ 4 files changed, 1127 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/can/arasan,canfd.yaml create mode 100644 drivers/net/can/arasan-canfd.c
Signature · 1 line
2.53.0
PATCH 1/2 dt-bindings: can: add arasan canfd controller
Add documentation for the arasan canfd controller.
--- .../bindings/net/can/arasan,canfd.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/can/arasan,canfd.yaml
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +63 -0
@@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/can/arasan,canfd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: + Arasan CAN-FD controller + +maintainers: + - Jisheng Zhang <[email protected]> + +allOf: + - $ref: can-controller.yaml# + +properties: + compatible: + const: arasan,canfd + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 2 + + clock-names: + items: + - const: can + - const: sys + + resets: + maxItems: 2 + + reset-names: + items: + - const: can + - const: sys + +required: + - compatible + - reg + - interrupts + - clocks + - resets + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + can@e5060000 { + compatible = "arasan,canfd"; + reg = <0xe5060000 0x1000>; + interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk 32>, <&clk 16>; + clock-names = "can", "sys"; + resets = <&rst 3>, <&rst 2>; + reset-names = "can", "sys"; + };
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH 1/2] dt-bindings: can: add arasan canfd controller
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] The schema uses `additionalProperties: false` instead of `unevaluatedProperties: false`, which…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The schema uses additionalProperties: false instead of unevaluatedProperties: false, which breaks property inheritance from can-controller.yaml.
- [Medium] Missing clock-names and reset-names in the required list, and missing minItems constraints.
--
--- Patch [1]: [PATCH 1/2] dt-bindings: can: add arasan canfd controller --- commit 282ace981cf63f65fd400dda84f1806d370fbc9b
Author: Jisheng Zhang <[email protected]>
dt-bindings: can: add arasan canfd controller
This commit adds device tree binding documentation for the Arasan CAN-FD controller.
Quoted 5 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +0
-0
[ ... ]
Quoted 2 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +2
-0+allOf: + - $ref: can-controller.yaml#
[ ... ]
Quoted 12 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +12
-0+ clocks: + maxItems: 2 + + clock-names: + items: + - const: can + - const: sys + + resets: + maxItems: 2 + + reset-names:
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml line 47
Quoted 10 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +10
-0+ items: + - const: can + - const: sys + +required: + - compatible + - reg + - interrupts + - clocks + - resets
[Severity: Medium]
Should clock-names and reset-names be included in this required list? A device tree omitting these names might pass validation, but could cause the driver to fail during probe when requesting clocks or resets by name.
Also, should clocks and resets specify minItems: 2, since the definition expects two distinct items for each?
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml
Quoted 2 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +2
-0+ +additionalProperties: false
[Severity: Medium]
Should this use unevaluatedProperties: false instead? Since the schema includes can-controller.yaml via $ref earlier in the file, using additionalProperties:
false will prevent the inheritance of valid standard properties from the included schema.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCH 1/2] dt-bindings: can: add arasan canfd controller
In reply to Jisheng ZhangQuoted 1 line · Jisheng Zhang
Add documentation for the arasan canfd controller.
Here goes hardware description. What is arasan canfd?
Quoted 21 lines
Signed-off-by Jisheng Zhang <[email protected]>--- .../bindings/net/can/arasan,canfd.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/can/arasan,canfd.yamlDocumentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +8
-0@@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/can/arasan,canfd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: + Arasan CAN-FD controller
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml line 18
Quoted 10 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +10
-0+ +maintainers: + - Jisheng Zhang <[email protected]> + +allOf: + - $ref: can-controller.yaml# + +properties: + compatible: + const: arasan,canfd
This is way too generic. Why isn't there any integration compatible?
Please follow writing bindings.
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml line 27
Quoted 9 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +9
-0+ + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 2
Instead list and describe items
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml line 31
Quoted 4 lines
Documentation/devicetree/bindings/net/can/arasan,canfd.yaml new file +4
-0+ + clock-names: + items: + - const: can
can is too generic, not really useful. Same for resets.
Best regards,
Krzysztof
PATCH 2/2 can: arasan-canfd: add driver for arasan CAN-FD controller
In reply to Jisheng ZhangAdd driver for the arasan CAN-FD controller.
--- drivers/net/can/Kconfig | 6 + drivers/net/can/Makefile | 1 + drivers/net/can/arasan-canfd.c | 1057 ++++++++++++++++++++++++++++++++ 3 files changed, 1064 insertions(+) create mode 100644 drivers/net/can/arasan-canfd.c
drivers/net/can/Kconfig +6 -0
@@ -83,6 +83,12 @@ config CAN_CALC_BITTIMING config CAN_RX_OFFLOAD bool +config CAN_ARASAN_CANFD + tristate "Arasan CAN FD controller" + depends on COMMON_CLK && HAS_IOMEM + help + Say Y here if you want to support for Arasan CAN FD. + config CAN_AT91 tristate "Atmel AT91 onchip CAN controller" depends on (ARCH_AT91 || COMPILE_TEST) && HAS_IOMEM
drivers/net/can/Makefile +1 -0
@@ -15,6 +15,7 @@ obj-y += spi/ obj-y += usb/ obj-y += softing/ +obj-$(CONFIG_CAN_ARASAN_CANFD) += arasan-canfd.o obj-$(CONFIG_CAN_AT91) += at91_can.o obj-$(CONFIG_CAN_BXCAN) += bxcan.o obj-$(CONFIG_CAN_CAN327) += can327.o
drivers/net/can/arasan-canfd.c new file +1057 -0
1,057 lines not on this page · raw message
Signature · 1 line
2.53.0
[email protected]
AI reviewRe: [PATCH 2/2] can: arasan-canfd: add driver for arasan CAN-FD controller
Thank you for your contribution! Sashiko AI review found 16 potential issue(s) to consider: - [Critical] Divide-by-zero kernel panic when configuring the device in standard CAN 2.0 mode. - [High]…
Thank you for your contribution! Sashiko AI review found 16 potential issue(s) to consider:
- [Critical] Divide-by-zero kernel panic when configuring the device in standard CAN 2.0 mode.
- [High] Off-by-one and potential negative index bypass in RX/TX queue index validation.
- [High] Uninitialized kernel stack memory is copied to the DMA buffer and leaked.
- [High] Missing NAPI work_done accounting on SKB allocation failure or TX abort causes infinite softirq loop.
- [High] Incorrect operator precedence corrupts Extended CAN IDs during reception.
- [High] Enabling NAPI after enabling hardware interrupts causes a permanent stall if an interrupt fires early.
- [High] Pending NAPI poll can run concurrently with system suspend, accessing powered-down hardware.
- [High] Driver completely ignores CAN framework Bit Timing configurations.
- [High] Unhandled TX aborts permanently leak TX queue slots and stall transmission.
- [Medium] Asynchronous pm_runtime_put() is cancelled by pm_runtime_disable(), leaving hardware incorrectly powered on and leaking clocks.
- [Medium] Leaking Linux internal CAN flags into hardware TX registers.
- [Medium] Inconsistent internal state transitioning when multiple bus error interrupts trigger.
- [Medium] Lockless call to netif_stop_queue on the TX error path can race with netif_wake_queue.
- [Medium] Missing dma_wmb() and dma_rmb() barriers when interacting with DMA buffers and device registers using relaxed I/O.
- [Medium] Truncation of 64-bit DMA addresses causing hardware misdirection.
- [Medium] DMA descriptors and data are processed using CPU-native byte order without endianness conversions.
--
--- Patch [2]: [PATCH 2/2] can: arasan-canfd: add driver for arasan CAN-FD controller --- commit fa1764e16e0ce790d11207dabd342ce03079236b
Author: Jisheng Zhang <[email protected]>
can: arasan-canfd: add driver for arasan CAN-FD controller
Add driver for the arasan CAN-FD controller.
Quoted 5 lines
drivers/net/can/arasan-canfd.c new file +0
-0
[ ... ]
Quoted 6 lines
drivers/net/can/arasan-canfd.c new file +6
-0+static int arasan_canfd_set_bittiming (struct net_device *ndev) +{ +struct arasan_canfd_priv *priv =netdev_priv (ndev); +struct can_bittiming *bt = &priv->can.bittiming; +struct can_bittiming *dbt = &priv->can.fd.data_bittiming; +u32 cl_2, cl_4, fd_2, fd_4, classic_cycle, fd_cycle;
[ ... ]
drivers/net/can/arasan-canfd.c line 292
Quoted 1 line
drivers/net/can/arasan-canfd.c new file +1
-0+ fd_cycle = priv->can.clock.freq / dbt->bitrate;
[Severity: Critical]
Can this cause a divide-by-zero crash when configuring the device in standard CAN 2.0 mode?
When the interface is brought up without CAN FD mode enabled, the CAN framework does not populate the fd.data_bittiming structure, leaving dbt->bitrate as 0.
drivers/net/can/arasan-canfd.c line 297
Quoted 5 lines
drivers/net/can/arasan-canfd.c new file +5
-0+ fd_2 = fd_cycle /2 ; + fd_4 = fd_cycle /4 ; +arasan_canfd_write (priv,LVL_FD_BAUD , fd_cycle); +arasan_canfd_write (priv,LVL_ALLOWABLE_FD_JUMP , fd_2); +arasan_canfd_write (priv,LVL_FD_END_OF_SYNC_SEG , fd_4);
[Severity: High]
Does this driver completely bypass the CAN framework's calculated timing parameters?
The code derives cycle lengths directly from the clock frequency and assigns fixed proportions for timing segments instead of using the calculated values in bt like bt->prop_seg, bt->phase_seg1, and bt->sjw. This prevents userspace from configuring specific sample points via netlink.
[ ... ]
Quoted 2 lines
drivers/net/can/arasan-canfd.c new file +2
-0+static void arasan_canfd_err_interrupt (struct net_device *ndev,u32 isr) +{
[ ... ]
drivers/net/can/arasan-canfd.c line 405
Quoted 9 lines
drivers/net/can/arasan-canfd.c new file +9
-0+if (isr &BUS_STATE2 ) { + priv->can.state =CAN_STATE_BUS_OFF ; + priv->can.can_stats.bus_off++; +can_bus_off (ndev); + cf.can_id |=CAN_ERR_BUSOFF ; + } + +if (isr &BUS_STATE1 ) { + priv->can.state =CAN_STATE_ERROR_PASSIVE ;
[Severity: Medium]
Could an independent evaluation of these states cause a lower-priority state to overwrite a terminal state?
If the hardware latches both conditions simultaneously, the driver processes Bus Off, but then immediately processes Error Passive and overwrites the internal state to CAN_STATE_ERROR_PASSIVE, breaking the CAN state machine. Should this use an else if structure?
[ ... ]
drivers/net/can/arasan-canfd.c line 430
Quoted 5 lines
drivers/net/can/arasan-canfd.c new file +5
-0+static void arasan_canfd_write_frame (struct net_device *ndev,struct sk_buff *skb,int idx) +{ +struct canfd_frame *cf = (struct canfd_frame *)skb->data; +struct arasan_canfd_priv *priv =netdev_priv (ndev); +struct can_tx_frame tx_frame;
[Severity: High]
Does allocating tx_frame on the stack without initializing it leak kernel memory?
The code copies only cf->len bytes into the data array, leaving the remainder of the 64-byte array and the resv_0 field uninitialized. The entire 76-byte structure is then copied into the DMA-mapped buffer, potentially leaking uninitialized kernel stack data to the device.
drivers/net/can/arasan-canfd.c line 435
Quoted 5 lines
drivers/net/can/arasan-canfd.c new file +5
-0+u32 *data = (u32 *)&tx_frame; +u8 *ecc = priv->buf->ecc_buffer.read.tx_frames[idx]; +int i; + + tx_frame.header.header0 =can_fd_len2dlc (cf->len);
[Severity: Medium]
Are these CPU-native bitwise operations and assignments safe on big-endian architectures?
The DMA descriptors are populated using CPU-native types and directly copied to DMA memory. On big-endian systems, this data will be stored in big-endian format. If the hardware expects little-endian byte ordering, it will interpret swapped bits.
drivers/net/can/arasan-canfd.c line 442
Quoted 7 lines
drivers/net/can/arasan-canfd.c new file +7
-0+ +if (cf->can_id &CAN_EFF_FLAG ) { +/* Extended CAN ID format */ + tx_frame.header.header0 |=TX_HEADER0_IDE ; + tx_frame.header.header0 |=FIELD_PREP (TX_HEADER0_ID , + (cf->can_id &CAN_EFF_MASK ) >>18 ); + tx_frame.header.ext_id = cf->can_id;
[Severity: Medium]
Does this direct assignment write Linux internal CAN flags into the hardware descriptor?
cf->can_id contains internal flags such as CAN_EFF_FLAG and CAN_RTR_FLAG. Writing these directly into the hardware's TX descriptor field might corrupt hardware configuration bits. Should this be masked using CAN_EFF_MASK?
[ ... ]
drivers/net/can/arasan-canfd.c line 474
Quoted 8 lines
drivers/net/can/arasan-canfd.c new file +8
-0+memcpy (tx_frame.data, cf->data, cf->len); + priv->buf->r_buffer.tx_frames[idx] = tx_frame; + +for (i =0 ; i <sizeof (tx_frame) /sizeof (u32); i++) + ecc[i] =ecc_calc (data[i]); + +arasan_canfd_write (priv,HITXFIFO , + priv->buf_dma + offsetof(struct can_buffer, r_buffer.tx_frames[idx]));
[Severity: Medium]
Is a dma_wmb() barrier needed here before writing to the HITXFIFO register?
Because writel_relaxed lacks memory ordering guarantees, the CPU can reorder the register write before the DMA memory writes complete, potentially causing the hardware to transmit stale data.
[ ... ]
drivers/net/can/arasan-canfd.c line 511
Quoted 11 lines
drivers/net/can/arasan-canfd.c new file +11
-0+static netdev_tx_t arasan_canfd_start_xmit (struct sk_buff *skb,struct net_device *ndev) +{ +int ret; + +if (can_dev_dropped_skb (ndev, skb)) +return NETDEV_TX_OK ; + + ret =arasan_canfd_start_xmit_queue (skb, ndev); +if (ret <0 ) { +netdev_err (ndev,"BUG!, TX full when queue awake!\n" ); +netif_stop_queue (ndev);
[Severity: Medium]
Can this lockless call to netif_stop_queue race with netif_wake_queue?
If a concurrent TX completion occurs right after arasan_canfd_start_xmit_queue releases the lock, the completion handler will free a slot and call netif_wake_queue. This lockless netif_stop_queue could then execute, overwriting the wake and deadlocking transmission.
Quoted 8 lines
drivers/net/can/arasan-canfd.c new file +8
-0+return NETDEV_TX_BUSY ; + } + +return NETDEV_TX_OK ; +} + +static int arasan_canfd_tx (struct net_device *ndev,unsigned long addr) +{
drivers/net/can/arasan-canfd.c line 529
Quoted 10 lines
drivers/net/can/arasan-canfd.c new file +10
-0+struct arasan_canfd_priv *priv =netdev_priv (ndev); +struct net_device_stats *stats = &ndev->stats; +int idx; + +guard (spinlock)(&priv->tx_lock); + + idx = (addr - priv->buf_dma - offsetof(struct can_buffer, r_buffer.tx_frames)) / +sizeof (struct can_tx_frame ); +if (idx >CAN_MAX_TX_QUEUE ) +return 0 ;
[Severity: High]
Does this bounds check fail to protect against negative index values?
The driver calculates the signed integer idx by subtracting priv->buf_dma from a hardware-provided address. If the hardware address is unexpectedly small, it can cause unsigned wrap-around, resulting in a negative value when cast to int. A negative value passes the idx > CAN_MAX_TX_QUEUE check. Additionally, the check uses > instead of >=, so idx == CAN_MAX_TX_QUEUE passes, causing an off-by-one out-of-bounds access.
[ ... ]
Quoted 4 lines
drivers/net/can/arasan-canfd.c new file +4
-0+static int arasan_canfd_rx (struct net_device *ndev,unsigned long addr) +{ +struct arasan_canfd_priv *priv =netdev_priv (ndev); +struct net_device_stats *stats = &ndev->stats;
drivers/net/can/arasan-canfd.c line 553
Quoted 10 lines
drivers/net/can/arasan-canfd.c new file +10
-0+struct canfd_frame *cf; +struct sk_buff *skb; +u32 header0, header1, header2; +struct can_rx_frame *rx_frame; +int idx, type; + + idx = (addr - priv->buf_dma - offsetof(struct can_buffer, w_buffer.rx_frames)) / +sizeof (struct can_rx_frame ); +if (idx >CAN_MAX_RX_QUEUE ) +return 0 ;
[Severity: High]
Does this bounds check have the same off-by-one and negative index bypass issue as the TX path?
The idx calculation can produce a negative integer or exactly equal CAN_MAX_RX_QUEUE, both of which bypass this check and lead to out-of-bounds memory access.
[ ... ]
drivers/net/can/arasan-canfd.c line 569
Quoted 9 lines
drivers/net/can/arasan-canfd.c new file +9
-0+if (type ==RX_HEADER0_TYPE_FD ) + skb =alloc_canfd_skb (ndev, &cf); +else + skb =alloc_can_skb (ndev, (struct can_frame **)&cf); + +if (unlikely (!skb)) { + stats->rx_dropped++; +return 0 ; + }
[Severity: High]
Could returning 0 on allocation failure lead to an infinite softirq loop?
In the NAPI poll loop, work_done is incremented by the return value of this function. If this returns 0 under memory pressure, work_done is not advanced. Under continuous CAN traffic, work_done will never reach quota, and the poll loop will spin the CPU indefinitely in softirq context.
[ ... ]
drivers/net/can/arasan-canfd.c line 587
Quoted 5 lines
drivers/net/can/arasan-canfd.c new file +5
-0+if (header0 &RX_HEADER0_B_EXT ) { +/* The received frame is an Extended format frame */ + cf->can_id =FIELD_GET (RX_HEADER1_EXTID , header1); + cf->can_id |= (FIELD_GET (RX_HEADER0_ID_0_6 , header0) | + (FIELD_GET (RX_HEADER1_ID_7_10 , header1) <<7 ) <<18 );
[Severity: High]
Does faulty operator precedence corrupt the CAN ID reconstruction here?
Because the bitwise OR operator has lower precedence than the left shift operator, the compiler evaluates this as:
A | ((B << 7) << 18)
This means the lower 7 bits of the standard ID are never shifted up by 18, corrupting bits 0-6 instead.
[ ... ]
drivers/net/can/arasan-canfd.c line 619
Quoted 12 lines
drivers/net/can/arasan-canfd.c new file +12
-0+static int arasan_canfd_poll (struct napi_struct *napi,int quota) +{ +struct net_device *ndev = napi->dev; +struct arasan_canfd_priv *priv =netdev_priv (ndev); +u32 buf_cnt, ier; +int type, work_done =0 ; +unsigned long addr; + +while ((buf_cnt =arasan_canfd_read (priv,USED_BUFS_PTR_COUNT )) >0 && + (work_done < quota)) { + addr =arasan_canfd_read (priv,USED_BUFS_PTR ); + type =FIELD_GET (TYPE_MASK , addr);
[Severity: Medium]
Is a dma_rmb() barrier needed here after reading USED_BUFS_PTR?
Without a read memory barrier, the CPU might reorder memory accesses and read stale RX descriptor data in arasan_canfd_rx before the hardware has fully written it.
drivers/net/can/arasan-canfd.c line 631
Quoted 12 lines
drivers/net/can/arasan-canfd.c new file +12
-0+ addr &= ~TYPE_MASK ; +switch (type) { +case TYPE_RX : + work_done +=arasan_canfd_rx (ndev, addr); +arasan_canfd_write (priv,RX_PTR_BUFS , addr); +break ; +case TYPE_TX : + work_done +=arasan_canfd_tx (ndev, addr); +break ; +case TYPE_TX_ABORT : +netdev_err (ndev,"tx abort\n" ); +break ;
[Severity: High]
Does this TX abort case permanently leak TX queue slots?
This case does not extract the transmission index, free the socket buffer, or reclaim the queue slot. The SKB and TX queue slot are leaked, which will permanently stall transmission once the queue fills up. It also fails to increment work_done, risking a softirq stall similar to the RX allocation failure path.
[ ... ]
Quoted 2 lines
drivers/net/can/arasan-canfd.c new file +2
-0+static int arasan_canfd_open (struct net_device *ndev) +{
[ ... ]
drivers/net/can/arasan-canfd.c line 716
Quoted 8 lines
drivers/net/can/arasan-canfd.c new file +8
-0+ ret =arasan_canfd_chip_start (ndev); +if (ret <0 ) { +netdev_err (ndev,"arasan_canfd_chip_start failed!\n" ); + goto err_candev; + } + +napi_enable (&priv->napi); +netif_start_queue (ndev);
[Severity: High]
Does enabling NAPI after hardware interrupts are unmasked create a deadlock window?
arasan_canfd_chip_start enables hardware interrupts. If an interrupt fires before napi_enable is called, the ISR will mask the interrupt and schedule a NAPI poll. Since NAPI isn't enabled yet, the poll is discarded and the interrupt remains masked permanently.
[ ... ]
Quoted 2 lines
drivers/net/can/arasan-canfd.c new file +2
-0+static void arasan_canfd_init (struct arasan_canfd_priv *priv) +{
[ ... ]
drivers/net/can/arasan-canfd.c line 793
Quoted 3 lines
drivers/net/can/arasan-canfd.c new file +3
-0+/* setup base registers */ +arasan_canfd_write (priv,R_BASE_ADDR , + priv->buf_dma + offsetof(struct can_buffer , r_buffer));
[Severity: Medium]
Can this truncate a 64-bit DMA address?
priv->buf_dma can be a 64-bit address on platforms without a restricted DMA mask, but it is written directly into a 32-bit register. If the address is above 4GB, the hardware will be directed to the wrong memory location.
[ ... ]
drivers/net/can/arasan-canfd.c line 833
Quoted 12 lines
drivers/net/can/arasan-canfd.c new file +12
-0+static int arasan_canfd_suspend (struct device *dev) +{ +struct net_device *ndev =dev_get_drvdata (dev); + +if (netif_running (ndev)) { +netif_stop_queue (ndev); +netif_device_detach (ndev); +arasan_canfd_chip_stop (ndev); + } + +return pm_runtime_force_suspend (dev); +}
[Severity: High]
Can a pending NAPI poll run concurrently with system suspend here?
This function stops the chip but fails to call napi_disable() and disable_irq() to wait for and terminate concurrent executions. pm_runtime_force_suspend will shut off the device clocks, meaning a concurrent NAPI poll could access powered down hardware and cause a kernel panic.
[ ... ]
Quoted 2 lines
drivers/net/can/arasan-canfd.c new file +2
-0+static int arasan_canfd_probe (struct platform_device *pdev) +{
[ ... ]
drivers/net/can/arasan-canfd.c line 1014
Quoted 3 lines
drivers/net/can/arasan-canfd.c new file +3
-0+err_disableclks: +pm_runtime_put (priv->dev); +pm_runtime_disable (&pdev->dev);
[Severity: Medium]
Does pm_runtime_disable cancel the asynchronous suspend request?
Calling pm_runtime_disable immediately after an asynchronous pm_runtime_put cancels the pending suspend work. This means the suspend callback is never executed, leaving the hardware incorrectly powered on and leaking clocks. Should this use pm_runtime_put_sync instead?
[ ... ]
drivers/net/can/arasan-canfd.c line 1032
Quoted 8 lines
drivers/net/can/arasan-canfd.c new file +8
-0+static void arasan_canfd_remove (struct platform_device *pdev) +{ +struct net_device *ndev =platform_get_drvdata (pdev); +struct arasan_canfd_priv *priv =netdev_priv (ndev); + +unregister_candev (ndev); +netif_napi_del (&priv->napi); +pm_runtime_disable (&pdev->dev);
[Severity: Medium]
Does this also suffer from the cancelled asynchronous suspend issue?
unregister_candev invokes arasan_canfd_close, which performs an asynchronous pm_runtime_put. The immediate pm_runtime_disable cancels it, again leaking clocks and leaving the device powered on.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Re: [PATCH 2/2] can: arasan-canfd: add driver for arasan CAN-FD controller
In reply to Jisheng ZhangQuoted 10 lines · Jisheng Zhang
Add driver for the arasan CAN-FD controller.
Signed-off-by Jisheng Zhang <[email protected]>--- drivers/net/can/Kconfig | 6 + drivers/net/can/Makefile | 1 + drivers/net/can/arasan-canfd.c | 1057 ++++++++++++++++++++++++++++++++ 3 files changed, 1064 insertions(+) create mode 100644 drivers/net/can/arasan-canfd.c
[...]
Quoted 6 lines
drivers/net/can/arasan-canfd.c new file +0
-0@@ -0,0 +1,1057 @@
[...]
Quoted 17 lines
drivers/net/can/arasan-canfd.c new file +17
-0+static int arasan_canfd_probe (struct platform_device *pdev) +{ +struct net_device *ndev; +struct arasan_canfd_priv *priv; +struct phy *transceiver; +void __iomem *addr; +int ret; + + addr =devm_platform_ioremap_resource (pdev,0 ); +if (IS_ERR (addr)) +return PTR_ERR (addr); + + ndev =alloc_candev (sizeof (struct arasan_canfd_priv ),CAN_MAX_TX_QUEUE ); +if (!ndev) +return -ENOMEM ; + priv =netdev_priv (ndev); +
drivers/net/can/arasan-canfd.c line 926
Quoted 10 lines
drivers/net/can/arasan-canfd.c new file +10
-0+ priv->sys_rst =devm_reset_control_get (&pdev->dev,"sys" ); +if (IS_ERR (priv->sys_rst)) { +dev_err (&pdev->dev,"failed to get sys reset\n" ); + ret =PTR_ERR (priv->sys_rst); + goto err_free; + } +reset_control_assert (priv->sys_rst); +reset_control_deassert (priv->sys_rst); + + priv->can_rst =devm_reset_control_get (&pdev->dev,"can" );
Please use devm_reset_control_get_exclusive() directly.
regards
Philipp
Re: [PATCH 2/2] can: arasan-canfd: add driver for arasan CAN-FD controller
In reply to Jisheng ZhangQuoted 5 lines · Jisheng Zhang
Add driver for the arasan CAN-FD controller.
drivers/net/can/arasan-canfd.c new file +2
-0+ +static const u32 ecc_syndrom[7 ] = {
drivers/net/can/arasan-canfd.c line 232
Quoted 10 lines
drivers/net/can/arasan-canfd.c new file +10
-0+0xC14840FF , +0x2124FF90 , +0x6CFF0808 , +0xFF01A444 , +0x16F092A6 , +0x101F7161 , + 0x8A820F1B, +}; + +static inline int parity (unsigned int x)
int / unsigned int ?
u32 might have been better.
Quoted 14 lines
drivers/net/can/arasan-canfd.c new file +14
-0+{ +/* +* public domain code snippet, lifted from +* http://www-graphics.stanford.edu/~seander/bithacks.html +*/ + x ^= x >>1 ; + x ^= x >>2 ; + x = (x &0x11111111U ) *0x11111111U ; +return (x >>28 ) &1 ; +} + +static u8 ecc_calc (u32 data) +{ +int i;
drivers/net/can/arasan-canfd.c line 256
Quoted 10 lines
drivers/net/can/arasan-canfd.c new file +10
-0+u8 result =0 ; + +for (i =0 ; i <7 ; i++) { +if (parity (data & ecc_syndrom[i])) + result |=BIT (i); + } + +return result; +} +
IIRC there's a even better solution with already existing kernel functions (e.g. hweight32()) which can use optimized CPU operations e.g. to count bits in a value than open coding the parity function.
#include <linux/bitops.h>
#include <linux/types.h>
static const u32 ecc_syndrom[7] = {
0xC14840FF,
0x2124FF90,
0x6CFF0808,
0xFF01A444,
0x16F092A6,
0x101F7161,
0x8A820F1B,
};static u8 ecc_calc(u32 data)
{
int i;
u8 result = 0;
for (i = 0; i < 7; i++) {
if (hweight32(data & ecc_syndrom[i]) & 1)
result |= BIT(i);
}
return result;
}Please re-check if you can use existing kernel code here.
Best regards,
Oliver