Re: [PATCH] alpha: add udelay to io port paths

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 5 Apr 2019, Mikulas Patocka wrote:

> > > I did some more testing and it turns out that mb() is not entirely 
> > > sufficient to prevent the boot hang. mb()'s latecy varies, sometimes it is 
> > > sufficient, sometimes not.
> > > 
> > > So, I submit this patch that adds 1us delay between any I/O accesses 
> > > directed at the ISA bus. This patch makes my machine boot. 1us seems to be 
> > > minimal acceptable value, with 800ns I still get hangs.
> > 
> >  Why wasn't the delay needed then before commit cd0e00c10672 ("alpha: io: 
> > reorder barriers to guarantee writeX() and iowriteX() ordering"), which 
> > only moved `mb' around?
> > 
> >   Maciej
> 
> Suppose that someone does
> outl(123, INDEX); x = inl(DATA);
> 
> Before the patch cd0e00c10672, the kernel would do
> __iowrite(123, INDEX);
> mb();
> x = __ioread(DATA);
> mb();
> 
> After the patch cd0e00c10672, the kernel would do
> mb();
> __iowrite(123, INDEX);
> x = __ioread(DATA);
> mb();
> 
> The patch changes the timing between the write and the read and the 
> hardware doesn't like it.

 Obviously you do need that `mb' before `__ioread' in the second case, 
just like in the first one, because otherwise the read bus access issued 
by `__ioread' can be reordered ahead of the write bus access issued by the 
preceding `__iowrite'.  A delay inserted by executing a loop out of cache 
will usually prevent such reordering as with the external bus being idle 
the write bus access issued by `__iowrite' will eventually have retired, 
but without an intervening `mb' it is not actually guaranteed that the 
retirement will happen ahead of `__ioread'.

 I hope I explained it clearly, however please do let me know if you think 
you are still missing something here.

 Also please mind Linus's note on a possible need to do a read back to 
make the write bus access retire right away (as Alpha does not have an 
explicit completion barrier instruction) in case a driver expects strict 
x86 semantics, e.g.:

/* Beginning of `outl'. */
mb();
__iowrite(123, INDEX);
mb();
__ioread(INDEX);
/* End of `outl'. */
/* Beginning of `inl'. */
mb();
x = __ioread(DATA);
mb();			/* Or `dma_rmb();'. */
/* End of `inl'. */

(though in reality it may actually be overly aggressive in terms of 
synchronisation, and also issuing `__ioread' to INDEX may not be safe in 
all cases, as it may cause side effects with some device registers, so 
another location may have to be used instead; e.g. for PCI port I/O 0x80 
might be a reasonable choice, at least for systems that have a south 
bridge).

  Maciej



[Index of Archives]     [Netdev]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux