On Mon, Aug 20, 2018 at 11:42 PM Mikulas Patocka <mpato...@redhat.com> wrote:
> On Mon, 20 Aug 2018, Arnd Bergmann wrote:
>
> > On Mon, Aug 20, 2018 at 4:17 PM Mikulas Patocka <mpato...@redhat.com> wrote:
> > > On Sun, 19 Aug 2018, ok...@codeaurora.org wrote:
> > >
> > > > +my new email
> > > >
> > > > On 2018-08-18 19:03, Arnd Bergmann wrote:
> > > > > On Sat, Aug 18, 2018 at 12:05 AM Maciej W. Rozycki 
> > > > > <ma...@linux-mips.org>
> >
> > > > I think we need to identify the driver that is failing.
> > >
> > > It also may be some timing issue.
> > >
> > > I observed that not every kernel with the patch
> > > 92d7223a74235054f2aa7227d207d9c57f84dca0 fails, some of them get stuck
> > > only at boot, some get stuck only at shutdown, some not at all. Although
> > > all the kernels with this patch reverted work.
> > >
> > > So the patch may have uncovered some timing problem somewhere.
> > >
> > > x86 has the function io_delay that injects delays between I/O accesses for
> > > hardware that needs it - does alpha have something like this?
> >
> > The I/O delay would be very low on my list of possible root causes
> > for this, hardly any hardware at all relies on it, and all uses I see
> > are related to outb(), which you've already shown not to be the problem
> > with my test patch.
> >
> The lockup happens somewhere in the function autoconfig in
> drivers/tty/serial/8250/8250_port.c, but I don't know where exactly
> because serial console doesn't work while the port is being probed.
>
> When I use console on a graphics card, the lockup doesn't happen.

Ok, this does strongly suggest that it is the outb() operation that I
suspected after all, I just sent you a wrong patch to test, failing
to realize that alpha has two implementations of outb, and that the
extern one is the one that gets used in a defconfig build.

Could you try again with this patch added in? (Sorry for the whitespace
damage, you'll have to apply it by hand). Presumably a wmb()
is sufficient here, but I'm trying to play safe here by restoring the
barrier that was part of outb() before it broke.

       Arnd

diff --git a/arch/alpha/kernel/io.c b/arch/alpha/kernel/io.c
index c025a3e5e357..604237fa821f 100644
--- a/arch/alpha/kernel/io.c
+++ b/arch/alpha/kernel/io.c
@@ -78,16 +78,19 @@ u32 inl(unsigned long port)
 void outb(u8 b, unsigned long port)
 {
        iowrite8(b, ioport_map(port, 1));
+       mb();
 }

 void outw(u16 b, unsigned long port)
 {
        iowrite16(b, ioport_map(port, 2));
+       mb();
 }

 void outl(u32 b, unsigned long port)
 {
        iowrite32(b, ioport_map(port, 4));
+       mb();
 }

 EXPORT_SYMBOL(inb);
@@ -336,6 +339,7 @@ void iowrite8_rep(void __iomem *port, const void
*xsrc, unsigned long count)
 void outsb(unsigned long port, const void *src, unsigned long count)
 {
        iowrite8_rep(ioport_map(port, 1), src, count);
+       mb();
 }

 EXPORT_SYMBOL(iowrite8_rep);
@@ -376,6 +380,7 @@ void iowrite16_rep(void __iomem *port, const void
*src, unsigned long count)
 void outsw(unsigned long port, const void *src, unsigned long count)
 {
        iowrite16_rep(ioport_map(port, 2), src, count);
+       mb();
 }

 EXPORT_SYMBOL(iowrite16_rep);
@@ -408,6 +413,7 @@ void iowrite32_rep(void __iomem *port, const void
*src, unsigned long count)
 void outsl(unsigned long port, const void *src, unsigned long count)
 {
        iowrite32_rep(ioport_map(port, 4), src, count);
+       mb();
 }

 EXPORT_SYMBOL(iowrite32_rep);

Reply via email to