From: Kevin Corry <kevcorry@us.ibm.com>
To: linuxppc-dev@ozlabs.org
Cc: LKML <linux-kernel@vger.kernel.org>, Carl Love <carll@us.ibm.com>
Subject: Questions about porting perfmon2 to powerpc
Date: Thu, 5 Apr 2007 14:55:33 -0500 [thread overview]
Message-ID: <200704051455.34600.kevcorry@us.ibm.com> (raw)
Hello,
Carl Love and I have been working on getting the latest perfmon2 patches
(http://perfmon2.sourceforge.net/) working on Cell, and on powerpc in
general. We've come up with some powerpc-specific questions and we're hoping
to get some opinions from the powerpc kernel developers.
First, the stock 2.6.20 kernel has a prototype in include/linux/smp.h for a
function called smp_call_function_single(). However, this routine is only
implemented on i386, x86_64, ia64, and mips. Perfmon2 apparently needs to
call this to run a function on a specific CPU. Powerpc provides an
smp_call_function() routine to run a function on all active CPUs, so I used
that as a basis to add an smp_call_function_single() routine. I've included
the patch below and was wondering if it looked like a sane approach.
Next, we ran into a problem related to Perfmon2 initialization and sysfs. The
problem turned out to be that the powerpc version of topology_init() is
defined as an __initcall() routine, but Perfmon2's initialization is done as
a subsys_initcall() routine. Thus, Perfmon2 tries to initialize its sysfs
information before some of the powerpc cpu information has been initialized.
However, on all other architectures, topology_init() is defined as a
subsys_initcall() routine, so this problem was not seen on any other
platforms. Changing the powerpc version of topology_init() to a
subsys_initcall() seems to have fixed the bug. However, I'm not sure if that
is going to cause problems elsewhere in the powerpc code. I've included the
patch below (after the smp-call-function-single patch). Does anyone know if
this change is safe, or if there was a specific reason that topology_init()
was left as an __initcall() on powerpc?
Thanks for your help!
--
Kevin Corry
kevcorry@us.ibm.com
http://www.ibm.com/linux/
===================================================================
Add an smp_call_function_single() to the powerpc architecture. This is mostly
a copy of smp_call_function(), but with minor modifications to call only the
specified CPU.
Index: linux-2.6.20-perfmon/arch/powerpc/kernel/smp.c
===================================================================
--- linux-2.6.20-perfmon.orig/arch/powerpc/kernel/smp.c
+++ linux-2.6.20-perfmon/arch/powerpc/kernel/smp.c
@@ -287,6 +287,92 @@ int smp_call_function (void (*func) (voi
EXPORT_SYMBOL(smp_call_function);
+/*
+ * This function sends a 'generic call function' IPI to the specified CPU.
+ *
+ * [SUMMARY] Run a function on the specified CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <nonatomic> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on the
+ * other CPU.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPU is nearly ready to execute <<func>> or are or has executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+int smp_call_function_single(int cpuid, void (*func)(void *info), void *info,
+ int nonatomic, int wait)
+{
+ struct call_data_struct data;
+ int ret = -1, cpus = 1, me;
+ u64 timeout;
+
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+
+ if (unlikely(smp_ops == NULL))
+ return -1;
+
+ me = get_cpu(); /* prevent preemption and reschedule on another processor */
+ if (cpuid == me) {
+ printk(KERN_INFO "%s: trying to call self\n", __FUNCTION__);
+ put_cpu();
+ return -EBUSY;
+ }
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ spin_lock(&call_lock);
+
+ call_data = &data;
+ smp_wmb();
+ /* Send a message to the specified CPU and wait for it to respond */
+ smp_ops->message_pass(cpuid, PPC_MSG_CALL_FUNCTION);
+
+ timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
+
+ /* Wait for response */
+ while (atomic_read(&data.started) != cpus) {
+ HMT_low();
+ if (get_tb() >= timeout) {
+ printk("%s on cpu %d: cpu %d not responding\n",
+ __FUNCTION__, smp_processor_id(), cpuid);
+ debugger(NULL);
+ goto out;
+ }
+ }
+
+ if (wait) {
+ while (atomic_read(&data.finished) != cpus) {
+ HMT_low();
+ if (get_tb() >= timeout) {
+ printk("%s on cpu %d: cpu %d not finishing\n",
+ __FUNCTION__, smp_processor_id(), cpuid);
+ debugger(NULL);
+ goto out;
+ }
+ }
+ }
+
+ ret = 0;
+
+ out:
+ call_data = NULL;
+ HMT_medium();
+ spin_unlock(&call_lock);
+ put_cpu();
+ return ret;
+}
+
+EXPORT_SYMBOL(smp_call_function_single);
+
void smp_call_function_interrupt(void)
{
void (*func) (void *info);
===================================================================
Change the powerpc version of topology_init() from an __initcall to
a subsys_initcall to match all other architectures.
Index: linux-2.6.20-perfmon/arch/powerpc/kernel/sysfs.c
===================================================================
--- linux-2.6.20-perfmon.orig/arch/powerpc/kernel/sysfs.c
+++ linux-2.6.20-perfmon/arch/powerpc/kernel/sysfs.c
@@ -455,4 +455,4 @@ static int __init topology_init(void)
return 0;
}
-__initcall(topology_init);
+subsys_initcall(topology_init);
===================================================================
next reply other threads:[~2007-04-05 19:55 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-05 19:55 Kevin Corry [this message]
2007-04-05 20:08 ` Questions about porting perfmon2 to powerpc Arnd Bergmann
2007-04-05 20:32 ` Kevin Corry
2007-04-05 20:37 ` Arnd Bergmann
2007-04-06 2:35 ` Kevin Corry
2007-04-05 23:04 ` Benjamin Herrenschmidt
2007-04-06 2:44 ` Kevin Corry
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200704051455.34600.kevcorry@us.ibm.com \
--to=kevcorry@us.ibm.com \
--cc=carll@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).