Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/opal: Wake up kopald polling thread before waiting for events

On some environments (prototype machines, some simulators, etc...)
there is no functional interrupt source to signal completion, so
we rely on the fairly slow OPAL heartbeat.

In a number of cases, the calls complete very quickly or even
immediately. We've observed that it helps a lot to wakeup the OPAL
heartbeat thread before waiting for event in those cases, it will
call OPAL immediately to collect completions for anything that
finished fast enough.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-By: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Benjamin Herrenschmidt and committed by
Michael Ellerman
a203658b 68a2d80c

+17 -2
+2
arch/powerpc/include/asm/opal.h
··· 292 292 return be64_to_cpu(msg.params[1]); 293 293 } 294 294 295 + void opal_wake_poller(void); 296 + 295 297 #endif /* __ASSEMBLY__ */ 296 298 297 299 #endif /* _ASM_POWERPC_OPAL_H */
+5
arch/powerpc/platforms/powernv/opal-async.c
··· 117 117 return -EINVAL; 118 118 } 119 119 120 + /* Wakeup the poller before we wait for events to speed things 121 + * up on platforms or simulators where the interrupts aren't 122 + * functional. 123 + */ 124 + opal_wake_poller(); 120 125 wait_event(opal_async_wait, test_bit(token, opal_async_complete_map)); 121 126 memcpy(msg, &opal_async_responses[token], sizeof(*msg)); 122 127
+10 -2
arch/powerpc/platforms/powernv/opal.c
··· 55 55 static DEFINE_SPINLOCK(opal_write_lock); 56 56 static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX]; 57 57 static uint32_t opal_heartbeat; 58 + static struct task_struct *kopald_tsk; 58 59 59 60 static void opal_reinit_cores(void) 60 61 { ··· 654 653 655 654 static int kopald(void *unused) 656 655 { 656 + unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1; 657 657 __be64 events; 658 658 659 659 set_freezable(); ··· 662 660 try_to_freeze(); 663 661 opal_poll_events(&events); 664 662 opal_handle_events(be64_to_cpu(events)); 665 - msleep_interruptible(opal_heartbeat); 663 + schedule_timeout_interruptible(timeout); 666 664 } while (!kthread_should_stop()); 667 665 668 666 return 0; 667 + } 668 + 669 + void opal_wake_poller(void) 670 + { 671 + if (kopald_tsk) 672 + wake_up_process(kopald_tsk); 669 673 } 670 674 671 675 static void opal_init_heartbeat(void) ··· 682 674 opal_heartbeat = 0; 683 675 684 676 if (opal_heartbeat) 685 - kthread_run(kopald, NULL, "kopald"); 677 + kopald_tsk = kthread_run(kopald, NULL, "kopald"); 686 678 } 687 679 688 680 static int __init opal_init(void)