Nathan Lynch via B4 Relay <devnull+nathanl.linux.ibm....@kernel.org> writes: > From: Nathan Lynch <nath...@linux.ibm.com> > > The kernel can handle retrying RTAS function calls in response to > -2/990x in the sys_rtas() handler instead of relaying the intermediate > status to user space.
This looks good in general. One query ... > diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c > index 47a2aa43d7d4..c330a22ccc70 100644 > --- a/arch/powerpc/kernel/rtas.c > +++ b/arch/powerpc/kernel/rtas.c > @@ -1798,7 +1798,6 @@ static bool block_rtas_call(int token, int nargs, > /* We assume to be passed big endian arguments */ > SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs) > { > - struct pin_cookie cookie; > struct rtas_args args; > unsigned long flags; > char *buff_copy, *errbuf = NULL; > @@ -1866,20 +1865,25 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, > uargs) > > buff_copy = get_errorlog_buffer(); > > - raw_spin_lock_irqsave(&rtas_lock, flags); > - cookie = lockdep_pin_lock(&rtas_lock); > + do { > + struct pin_cookie cookie; > > - rtas_args = args; > - do_enter_rtas(&rtas_args); > - args = rtas_args; > + raw_spin_lock_irqsave(&rtas_lock, flags); > + cookie = lockdep_pin_lock(&rtas_lock); > > - /* A -1 return code indicates that the last command couldn't > - be completed due to a hardware error. */ > - if (be32_to_cpu(args.rets[0]) == -1) > - errbuf = __fetch_rtas_last_error(buff_copy); > + rtas_args = args; > + do_enter_rtas(&rtas_args); > + args = rtas_args; > > - lockdep_unpin_lock(&rtas_lock, cookie); > - raw_spin_unlock_irqrestore(&rtas_lock, flags); > + /* > + * Handle error record retrieval before releasing the lock. > + */ > + if (be32_to_cpu(args.rets[0]) == -1) > + errbuf = __fetch_rtas_last_error(buff_copy); > + > + lockdep_unpin_lock(&rtas_lock, cookie); > + raw_spin_unlock_irqrestore(&rtas_lock, flags); > + } while (rtas_busy_delay(be32_to_cpu(args.rets[0]))); rtas_busy_delay_early() has the successive_ext_delays case that will break out eventually. But if we keep getting plain RTAS_BUSY back from RTAS I *think* this loop will never terminate? To avoid that, and just as good manners, I think we should have a fatal_signal_pending() check, and if that returns true we bail out of the syscall with -EINTR ? cheers