[PATCH 2/2] ARC: io: use asm-generic MMIO accessors
Vineet Gupta
vgupta at kernel.org
Wed Nov 4 18:57:22 PST 2026
On 11/3/26 23:40, Arnd Bergmann wrote:
> On Wed, Nov 4, 2026, at 05:35, Vineet Gupta wrote:
>> ARC MMIO accessors use inline asm, which isn't really needed. It was
>> introduced with the original port back in 2013.
>>
>> As the previous patch showed, inline asm can be error-prone. Letting the
>> compiler emit the accesses also allows 16-bit encodings, scaled-index
>> loads and folding constant offsets (s9) into the access.
>>
>> Without the asm, ARC's __raw_{read,write}{b,w,l}(), *_relaxed(),
>> {read,write}{b,w,l}() and io{read,write}{16,32}be() are the same as the
>> asm-generic/io.h versions, so drop them and use the generic ones.
> Hi Vineet,
>
> In my experience, the generic helpers are also fragile, they just lead
> to different problems when the compiler optimizes them in ways it
> should not.
>
> I would recommend keeping the __raw helpers with the workaround from
> the first patch, possibly both variants depending on the compiler
> version.
OK.
> Using the generic higher level interfaces is a very welcome change
> though, I hope we can eventually get to the point where every
> architecture just needs to provide the __raw_*() ones.
Yes that would be ideal but what we have today is not bad either. I was
trying to see if its possible to remove boilerplate.
>> Two things stay ARC-specific:
>>
>> - The barriers, now hooked into the generic accessors through
>> __io_ar()/__io_bw(). On ARCv2 they remain dmb (rmb()/wmb()).
>> On ARCompact they were empty, relying on the asm "memory" clobber
>> as a compiler barrier, so make them barrier() explicitly.
>> The generic defaults would be mb(), i.e. the heavyweight SYNC.
>> The *_relaxed() accessors only need ordering against other MMIO
>> accesses, which volatile guarantees.
> Sounds good.
>
>> - The {read,write}s{b,w,l}() string helpers, which, unlike the generic
>> ones, cope with an unaligned memory buffer. They are defined before
>> asm-generic/io.h is included, as it calls them (e.g. ioread8_rep()),
>> so they do the volatile access directly rather than via __raw_*().
> I don't think we want a custom version here. Do you know the reason this
> tries to handle unaligned buffers? If there are drivers that require it,
> we can change the generic implementation to be more like the arc version,
> otherwise this likely just causes larger object code for all users that
> don't ever need unaligned access.
Not specifically but one of my old notes mentions a driver calling
readsl as follows:
static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master,
u8 *bytes, int nbytes)
{
readsl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4);
if (nbytes & 3) {
u32 tmp;
readsl(master->regs + RX_TX_DATA_PORT, &tmp, 1);
memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3);
}
}
And with readsl at the time being as following was broken due to the
recast to int.
static inline void readsl(const volatile void __iomem *addr, void *buffer,
unsigned int count)
{
if (count) {
u32 *buf = buffer;
do {
u32 x = __raw_readl(addr);
*buf++ = x;
} while (--count);
}
}
Thx,
-Vineet
> I see that the sparc version does the same thing, other ones without
> unaligned access (in particular armv5 and riscv) assume that the
> memory buffer is aligned. On alpha and parisc, there is an alignment
> check for insl()/outsl() but not readsl()/writesl(). I suspect this
> is not intentional.
>
> If they do run into this problem, they will fix it up with a slow
> fault handler on the unaligned memory access.
>
> Arnd
More information about the linux-snps-arc
mailing list