powerpc/opal: Wake up kopald polling thread before waiting for events
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 4 Jul 2016 04:51:44 +0000 (14:51 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 8 Jul 2016 09:53:26 +0000 (19:53 +1000)
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>
arch/powerpc/include/asm/opal.h
arch/powerpc/platforms/powernv/opal-async.c
arch/powerpc/platforms/powernv/opal.c

index 3b369e9..52b9f4a 100644 (file)
@@ -292,6 +292,8 @@ static inline int opal_get_async_rc(struct opal_msg msg)
                return be64_to_cpu(msg.params[1]);
 }
 
+void opal_wake_poller(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
index bdc8c0c..83bebee 100644 (file)
@@ -117,6 +117,11 @@ int opal_async_wait_response(uint64_t token, struct opal_msg *msg)
                return -EINVAL;
        }
 
+       /* Wakeup the poller before we wait for events to speed things
+        * up on platforms or simulators where the interrupts aren't
+        * functional.
+        */
+       opal_wake_poller();
        wait_event(opal_async_wait, test_bit(token, opal_async_complete_map));
        memcpy(msg, &opal_async_responses[token], sizeof(*msg));
 
index 228751a..da40d6b 100644 (file)
@@ -55,6 +55,7 @@ struct device_node *opal_node;
 static DEFINE_SPINLOCK(opal_write_lock);
 static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
 static uint32_t opal_heartbeat;
+static struct task_struct *kopald_tsk;
 
 static void opal_reinit_cores(void)
 {
@@ -653,6 +654,7 @@ static void opal_i2c_create_devs(void)
 
 static int kopald(void *unused)
 {
+       unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1;
        __be64 events;
 
        set_freezable();
@@ -660,12 +662,18 @@ static int kopald(void *unused)
                try_to_freeze();
                opal_poll_events(&events);
                opal_handle_events(be64_to_cpu(events));
-               msleep_interruptible(opal_heartbeat);
+               schedule_timeout_interruptible(timeout);
        } while (!kthread_should_stop());
 
        return 0;
 }
 
+void opal_wake_poller(void)
+{
+       if (kopald_tsk)
+               wake_up_process(kopald_tsk);
+}
+
 static void opal_init_heartbeat(void)
 {
        /* Old firwmware, we assume the HVC heartbeat is sufficient */
@@ -674,7 +682,7 @@ static void opal_init_heartbeat(void)
                opal_heartbeat = 0;
 
        if (opal_heartbeat)
-               kthread_run(kopald, NULL, "kopald");
+               kopald_tsk = kthread_run(kopald, NULL, "kopald");
 }
 
 static int __init opal_init(void)