Re: [PATCH v2 2/2] mailbox: add Axiado AX3005 mailbox driver

Swark Yang <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-devicetree
Message-ID <[email protected]>
On 8/18/2026 11:44 AM, [email protected] wrote:
> 
> 
>> +     for (offset = 0; offset + sizeof(u32) <= msg_len;
>> +          offset += sizeof(u32))
>> +             writel(get_unaligned_le32(buf + offset), priv->mbox_reg);
> 
> [Severity: Medium]
> Since this loop writes bulk data to a FIFO, should it use the stream I/O
> accessor writesl() instead of writel()?
> 
> The io-accessors subsystem guidelines mandate using stream accessors for
> FIFOs to avoid unnecessary per-word memory barriers and redundant endianness
> conversions.
> 

The current per-word get_unaligned_le32()/writel() accesses are
intentional.
The mailbox message format is little-endian, and the buffer is not
guaranteed to be naturally aligned. The stream accessors are raw
transfers and do not provide the same explicit unaligned
little-endian handling, so replacing the current accesses
with writesl() is not a direct substitution.

I'll take another look at whether the stream accessors can be used
without changing those semantics before v3.

>> +     if (csr & AXIADO_MBOX_CSR_EMPTY)
>> +             return IRQ_NONE;
> 
> [Severity: High]
> If the interrupt was asserted solely due to a hardware error (like an
> underflow), axiado_mbox_clear_fifo_errors() successfully clears the condition.
> If the FIFO is empty afterwards, this check returns IRQ_NONE.
> 
> Does this risk permanently disabling the IRQ line? Returning IRQ_NONE after
> successfully servicing a hardware event can trigger the core spurious
> interrupt detector.
> 


Good point. Whether this case can occur depends on whether the FIFO
overflow/underflow status can itself assert the RX interrupt, rather
than the interrupt being driven only by the FIFO not-empty condition.

I'll verify the hardware interrupt semantics and adjust the return
handling in v3 if an error condition can independently cause the
interrupt.

>> +     if (remaining) {
>> +             ret = readl_poll_timeout(priv->csr_reg, csr,
>> +                                      (csr & AXIADO_MBOX_CSR_ERRORS) ||
>> +                                       FIELD_GET(AXIADO_MBOX_CSR_LEVEL, csr) >=
>> +                                       remaining,
> 
> [Severity: High]
> The poll condition succeeds if AXIADO_MBOX_CSR_ERRORS is set, terminating
> early without verifying the FIFO actually reached the required level.
> 
> If the loop exits early due to an error rather than the level check, the code
> continues to the for-loop below and blindly reads remaining words from the
> FIFO. Will this cause hardware underflows and pass garbage data to the
> mailbox client?
> 

Agreed. If the poll exits because AXIADO_MBOX_CSR_ERRORS is set before
the FIFO reaches the required level, the subsequent read loop can
proceed with an incomplete message.

The current code does not distinguish between "the remaining data
arrived" and "an error was observed while the data was still
incomplete". I'll fix this in v3 so that the read loop is entered
only after the required FIFO level has actually been reached, and
re-test the RX path.

>> +             word = readl(priv->mbox_reg);
> 
> [Severity: Medium]
> Similar to the TX path, does this bulk FIFO read need to use readsl() instead
> of readl() to avoid the per-word memory barriers and endianness swaps?
> 

Same consideration as for the TX path above. The current
readl()/put_unaligned_le32() sequence explicitly handles the
little-endian message format and a destination buffer that may not
be naturally aligned, so readsl() is not a direct replacement.
I'll include this in the stream-accessor review for v3.

>> +             put_unaligned_le32(word, buf + i * sizeof(u32));
>> +     }
>> +
>> +     axiado_mbox_clear_fifo_errors(priv);
>> +
>> +     if (READ_ONCE(priv->active))
>> +             mbox_chan_received_data(chan, priv->rx_buffer);
> 
> [Severity: High]
> Can mbox_free_channel() nullify the channel client pointer while this thread
> is preempted?
> 
> If a mailbox client frees the channel, mbox_free_channel() clears chan->cl
> under a lock, releases the lock, and calls axiado_mbox_shutdown(). If this
> threaded IRQ handler evaluates READ_ONCE(priv->active) as true just before
> being preempted, the shutdown routine will block in disable_irq().
> 
> When this handler resumes, will mbox_chan_received_data() dereference a NULL
> chan->cl pointer?
> 

I don't think this race applies here. mbox_free_channel() invokes the
controller's ->shutdown() before chan->cl is cleared, rather than
clearing chan->cl first.

axiado_mbox_shutdown() calls disable_irq(), which waits for any
in-flight interrupt handler, including the threaded handler, to
complete. Therefore, any concurrently running axiado_rx_thread() has
completed by the time shutdown returns, before chan->cl can be cleared.

Based on this ordering, I don't see a path where chan->cl can become
NULL while axiado_rx_thread() is still running.

Thanks,
Swark
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.