[PATCH] PowerPC: Fix num_cpus calculation in smp_call_function_map()

2007-07-31 Thread Kevin Corry
[POWERPC]: Fix num_cpus calculation in smp_call_function_map().

In smp_call_function_map(), num_cpus is set to the number of online CPUs minus
one. However, if the CPU mask does not include all CPUs (except the one we're
running on), the routine will hang in the first while() loop until the 8 second
timeout occurs.

The num_cpus should be set to the number of CPUs specified in the mask passed
into the routine, after we've made any modifications to the mask. With this
change, we can also get rid of the call to cpus_empty() and avoid adding
another pass through the bitmask.

Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>
Signed-off-by: Carl Love <[EMAIL PROTECTED]>

Index: linux-2.6.23-rc1/arch/powerpc/kernel/smp.c
===
--- linux-2.6.23-rc1.orig/arch/powerpc/kernel/smp.c
+++ linux-2.6.23-rc1/arch/powerpc/kernel/smp.c
@@ -212,11 +212,6 @@ int smp_call_function_map(void (*func) (
atomic_set(&data.finished, 0);
 
spin_lock(&call_lock);
-   /* Must grab online cpu count with preempt disabled, otherwise
-* it can change. */
-   num_cpus = num_online_cpus() - 1;
-   if (!num_cpus)
-   goto done;
 
/* remove 'self' from the map */
if (cpu_isset(smp_processor_id(), map))
@@ -224,7 +219,9 @@ int smp_call_function_map(void (*func) (
 
/* sanity check the map, remove any non-online processors. */
cpus_and(map, map, cpu_online_map);
-   if (cpus_empty(map))
+
+   num_cpus = cpus_weight(map);
+   if (!num_cpus)
goto done;
 
call_data = &data;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/2] powerpc: change topology_init() to a subsys_initcall

2007-05-03 Thread Kevin Corry
Hi Michael,

On Wed May 2 2007 8:11 pm, Michael Ellerman wrote:
> On Wed, 2007-05-02 at 12:11 -0500, Kevin Corry wrote:
> > Change the powerpc version of topology_init() from an __initcall to
> > a subsys_initcall to match all other architectures.
> >
> > Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>
> >
> > Index: linux-2.6.21/arch/powerpc/kernel/sysfs.c
> > ===
> > --- linux-2.6.21.orig/arch/powerpc/kernel/sysfs.c
> > +++ linux-2.6.21/arch/powerpc/kernel/sysfs.c
> > @@ -498,4 +498,4 @@ static int __init topology_init(void)
> >
> > return 0;
> >  }
> > -__initcall(topology_init);
> > +subsys_initcall(topology_init);
>
> topology_init() depends on the register_one_node() stuff being
> available, which relies on register_node_type() being called AFAICT -
> which is a postcore_initcall(). So that's OK.
>
> It also creates sysfs files, which is OK because long before initcalls
> run vfs_caches_init() called mnt_init() which called sysfs_init().
>
> Just to be super safe it'd be good to diff your sysfs before and after
> the change. But assuming that show's nothing this looks fine to me.

I booted with and without this patch applied, and the file listings of /sys on 
both kernels show no differences (other than timestamps).

Thanks for the feedback.
-- 
Kevin Corry
[EMAIL PROTECTED]
http://www.ibm.com/linux/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] powerpc: add smp_call_function_single()

2007-05-02 Thread Kevin Corry
Add an smp_call_function_single() to the powerpc architecture. Since this
is very similar to the existing smp_call_function() routine, the common
portions have been split out into __smp_call_function(). Since the
spin_lock(&call_lock) was moved to __smp_call_function(),
smp_call_function() now explicitly calls preempt_disable() before getting
the count of online CPUs.

Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>

Index: linux-2.6.21/arch/powerpc/kernel/smp.c
===
--- linux-2.6.21.orig/arch/powerpc/kernel/smp.c
+++ linux-2.6.21/arch/powerpc/kernel/smp.c
@@ -175,26 +175,11 @@ static struct call_data_struct {
 /* delay of at least 8 seconds */
 #define SMP_CALL_TIMEOUT   8
 
-/*
- * This function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- *
- * [SUMMARY] Run a function on all other CPUs.
- *  The function to run. This must be fast and non-blocking.
- *  An arbitrary pointer to pass to the function.
- *  currently unused.
- *  If true, wait (atomically) until function has completed on other 
CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <> or are or have 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 (void (*func) (void *info), void *info, int nonatomic,
-  int wait)
-{ 
+static int __smp_call_function(void (*func)(void *info), void *info,
+  int wait, int target_cpu, int num_cpus)
+{
struct call_data_struct data;
-   int ret = -1, cpus;
+   int ret = -1;
u64 timeout;
 
/* Can deadlock when called with interrupts disabled */
@@ -211,40 +196,33 @@ int smp_call_function (void (*func) (voi
atomic_set(&data.finished, 0);
 
spin_lock(&call_lock);
-   /* Must grab online cpu count with preempt disabled, otherwise
-* it can change. */
-   cpus = num_online_cpus() - 1;
-   if (!cpus) {
-   ret = 0;
-   goto out;
-   }
 
call_data = &data;
smp_wmb();
/* Send a message to all other CPUs and wait for them to respond */
-   smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
+   smp_ops->message_pass(target_cpu, PPC_MSG_CALL_FUNCTION);
 
timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
 
/* Wait for response */
-   while (atomic_read(&data.started) != cpus) {
+   while (atomic_read(&data.started) != num_cpus) {
HMT_low();
if (get_tb() >= timeout) {
-   printk("smp_call_function on cpu %d: other cpus not "
-  "responding (%d)\n", smp_processor_id(),
-  atomic_read(&data.started));
+   printk("%s on cpu %d: other cpus not "
+  "responding (%d)\n", __FUNCTION__,
+  smp_processor_id(), atomic_read(&data.started));
debugger(NULL);
goto out;
}
}
 
if (wait) {
-   while (atomic_read(&data.finished) != cpus) {
+   while (atomic_read(&data.finished) != num_cpus) {
HMT_low();
if (get_tb() >= timeout) {
-   printk("smp_call_function on cpu %d: other "
-  "cpus not finishing (%d/%d)\n",
-  smp_processor_id(),
+   printk("%s on cpu %d: other cpus "
+  "not finishing (%d/%d)\n",
+  __FUNCTION__, smp_processor_id(),
   atomic_read(&data.finished),
   atomic_read(&data.started));
debugger(NULL);
@@ -262,8 +240,74 @@ int smp_call_function (void (*func) (voi
return ret;
 }
 
+/*
+ * This function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ *
+ * [SUMMARY] Run a function on all other CPUs.
+ *  The function to run. This must be fast and non-blocking.
+ *  An arbitrary pointer to pass to the function.
+ *  currently unused.
+ *  If true, wait (atomically) until function has completed on other 
CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler o

[PATCH 2/2] powerpc: change topology_init() to a subsys_initcall

2007-05-02 Thread Kevin Corry
Change the powerpc version of topology_init() from an __initcall to
a subsys_initcall to match all other architectures.

Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>

Index: linux-2.6.21/arch/powerpc/kernel/sysfs.c
===
--- linux-2.6.21.orig/arch/powerpc/kernel/sysfs.c
+++ linux-2.6.21/arch/powerpc/kernel/sysfs.c
@@ -498,4 +498,4 @@ static int __init topology_init(void)
 
return 0;
 }
-__initcall(topology_init);
+subsys_initcall(topology_init);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] powerpc: perfmon2 prereqs

2007-05-02 Thread Kevin Corry
Hi,

This is a repost of a couple patches I posted about a month ago related to 
porting perfmon2 to powerpc. I wanted to see if there were any further 
comments on these patches, and also wanted to ask if these should be 
submitted separately to the ppc kernel maintainers, or if they should be kept 
with the perfmon2 patches until those are submitted.

The first patch adds an smp_call_function_single() routine for powerpc. In 
2.6.21, there's a prototype for this routine in include/linux/smp.h, and it 
is implemented on i386, ia64, and x86-64. Since this routine is very similar 
to the existing smp_call_function() routine, the common portions have been 
pulled out into __smp_call_function(). Perfmon2 uses this unload a context 
that's loaded on a CPU other than the one that's performing the close-context 
routine.

The second patch changes the powerpc version of topology_init() from an 
__initcall to a subsys_initcall, which matches the definition of 
topology_init() on all other architectures. Perfmon2's initialization is done 
as a subsys_initcall, but it fails to set up its sysfs information if 
topology_init() has not yet run. Changing perfmon2 to an __initcall() was 
discussed, but we came to the conclusion that this would not work because the 
perfmon2 core must be initialized before any of its sub-modules. These 
sub-modules are located in arch/*/perfmon/, and thus if they are built 
statically they would run their module_init routines before the perfmon2 core 
ran its __initcall routine.

We have been running tests with these patches for the last few weeks on Cell 
and Power5 systems without any problems.

Thanks,
-- 
Kevin Corry
[EMAIL PROTECTED]
http://www.ibm.com/linux/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Questions about porting perfmon2 to powerpc

2007-04-05 Thread Kevin Corry
On Thu April 5 2007 6:04 pm, Benjamin Herrenschmidt wrote:
> On Thu, 2007-04-05 at 14:55 -0500, Kevin Corry wrote:
> > 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.
>
> We should do better... it will require some backend work for the various
> supported PICs though. I've always wanted to look into doing a 
> smp_call_function_cpumask in fact :-)

I was actually wondering about that myself today. It would seem like an 
smp_call_function() that takes a CPU mask would be much more flexible than 
either the current version or the new one that I proposed. However, that was 
a little more hacking that I was willing to do today on powerpc architecture 
code. :)

> > 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?
>
> It would make sense to follow what other archs do. Note that if both
> perfmon and topology_init are subsys_initcall, that is on the same
> level, it's still a bit hairy to expect one to be called before the
> other...

I wondered that as well, but based on what Arnd posted earlier (presumably 
about the kernel linking order), the topology_init() call, which is in the 
arch/ top-level directory, should occur before pfm_init(), which is in 
perfmon/, even if both are in the same initcall level.

Thanks,
-- 
Kevin Corry
[EMAIL PROTECTED]
http://www.ibm.com/linux/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Questions about porting perfmon2 to powerpc

2007-04-05 Thread Kevin Corry
On Thu April 5 2007 3:32 pm, Kevin Corry wrote:
> On Thu April 5 2007 3:08 pm, Arnd Bergmann wrote:
> > On Thursday 05 April 2007, Kevin Corry wrote:
> > > 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.
> >
> > The function itself looks good, but since it's very similar to the
> > existing smp_call_function(), you should probably try to share some of
> > the code, e.g. by making a helper function that gets an argument to
> > decide whether to run on a specific CPU or on all CPUs.
>
> Ok. I'll see what I can come up with and post another patch today or
> tomorrow.

Here's a new version that adds smp_call_function_single(), and moves the
code that's shared with smp_call_function() to __smp_call_function().

Thanks,
-- 
Kevin Corry
[EMAIL PROTECTED]
http://www.ibm.com/linux/


Add an smp_call_function_single() to the powerpc architecture. Since this
is very similar to the existing smp_call_function() routine, the common
portions have been split out into __smp_call_function(). Since the
spin_lock(&call_lock) was moved to __smp_call_function(),
smp_call_function() now explicitly calls preempt_disable() before getting
the count of online CPUs.

Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>

Index: linux-2.6.20-arnd3-perfmon/arch/powerpc/kernel/smp.c
===
--- linux-2.6.20-arnd3-perfmon.orig/arch/powerpc/kernel/smp.c
+++ linux-2.6.20-arnd3-perfmon/arch/powerpc/kernel/smp.c
@@ -198,26 +198,11 @@ static struct call_data_struct {
 /* delay of at least 8 seconds */
 #define SMP_CALL_TIMEOUT   8
 
-/*
- * This function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- *
- * [SUMMARY] Run a function on all other CPUs.
- *  The function to run. This must be fast and non-blocking.
- *  An arbitrary pointer to pass to the function.
- *  currently unused.
- *  If true, wait (atomically) until function has completed on other 
CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <> or are or have 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 (void (*func) (void *info), void *info, int nonatomic,
-  int wait)
-{ 
+static int __smp_call_function(void (*func)(void *info), void *info,
+  int wait, int target_cpu, int num_cpus)
+{
struct call_data_struct data;
-   int ret = -1, cpus;
+   int ret = -1;
u64 timeout;
 
/* Can deadlock when called with interrupts disabled */
@@ -234,40 +219,33 @@ int smp_call_function (void (*func) (voi
atomic_set(&data.finished, 0);
 
spin_lock(&call_lock);
-   /* Must grab online cpu count with preempt disabled, otherwise
-* it can change. */
-   cpus = num_online_cpus() - 1;
-   if (!cpus) {
-   ret = 0;
-   goto out;
-   }
 
call_data = &data;
smp_wmb();
/* Send a message to all other CPUs and wait for them to respond */
-   smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
+   smp_ops->message_pass(target_cpu, PPC_MSG_CALL_FUNCTION);
 
timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
 
/* Wait for response */
-   while (atomic_read(&data.started) != cpus) {
+   while (atomic_read(&data.started) != num_cpus) {
HMT_low();
if (get_tb() >= timeout) {
-   printk("smp_call_function on cpu %d: other cpus not "
-  "responding (%d)\n", smp_processor_id(),
-  atomic_read(&data.started));
+   printk("%s on cpu %d: other cpus not "
+  "responding (%d)\n", __FUNCTION__,
+  smp_processor_id(), atomic_read(&data.started));
debugger(NULL);
goto out;
}
}
 
if (wait) {
-   while (atomic_read(&data.finished) != cpus) {
+   while (atomic_read(&data.

Re: Questions about porting perfmon2 to powerpc

2007-04-05 Thread Kevin Corry
On Thu April 5 2007 3:08 pm, Arnd Bergmann wrote:
> On Thursday 05 April 2007, Kevin Corry wrote:
> > 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.
>
> The function itself looks good, but since it's very similar to the existing
> smp_call_function(), you should probably try to share some of the code,
> e.g. by making a helper function that gets an argument to decide whether
> to run on a specific CPU or on all CPUs.

Ok. I'll see what I can come up with and post another patch today or tomorrow.


> > 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?
>
> In general, it's better to do initcalls as late as possible, so
> __initcall() is preferred over subsys_initcall() if both work. Have you
> tried doing it the other way and starting perfmon2 from a regular
> __initcall()?

For the moment, I made the change to topology_init() since it was the simplest 
fix to get things working. I have considered switching the perfmon2 
initialization to __initcall(), but there are apparently some timing issues 
with ensuring that the perfmon2 core code is initialized before any of its 
sub-modules. Since they could all be compiled statically in the kernel, I'm 
not sure if there's a way to ensure the ordering of calls within a single 
initcall level. I'll need to ask Stephane if there were any other reasons why 
subsys_initcall() was used for perfmon2.

Thanks, Arnd.
-- 
Kevin Corry
[EMAIL PROTECTED]
http://www.ibm.com/linux/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Questions about porting perfmon2 to powerpc

2007-04-05 Thread Kevin Corry
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
[EMAIL PROTECTED]
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.
+ *  The function to run. This must be fast and non-blocking.
+ *  An arbitrary pointer to pass to the function.
+ *  currently unused.
+ *  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 <> 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

Re: device-mapper: fix TB stripe data corruption

2005-01-21 Thread Kevin Corry
On Friday 21 January 2005 3:20 pm, Roland Dreier wrote:
> Kevin> We have to take a mod of the chunk value and the number of
> Kevin> stripes (which can be a non-power-of-2, so a shift won't
> Kevin> work). It's been my understanding that you couldn't mod a
> Kevin> 64-bit value with a 32-bit value in the kernel.
>
> If I understand you correctly, do_div() (defined in )
> does what you need.  Look at asm-generic/div64.h for a good
> description of the precise semantics of do_div().

Thanks for the tip, Roland. That seems to be exactly what we needed.  Here's a 
different version of Alasdair's patch that changes chunk to 64-bit and uses 
do_div().

-- 
Kevin Corry
[EMAIL PROTECTED]
http://evms.sourceforge.net/


In stripe_map(), change chunk to 64-bit and use do_div to divide and mod by
the number of stripes.

--- diff/drivers/md/dm-stripe.c 2005-01-21 15:55:02.093379864 -0600
+++ source/drivers/md/dm-stripe.c 2005-01-21 15:54:25.400957960 -0600
@@ -173,9 +173,8 @@
  struct stripe_c *sc = (struct stripe_c *) ti->private;
 
  sector_t offset = bio->bi_sector - ti->begin;
- uint32_t chunk = (uint32_t) (offset >> sc->chunk_shift);
- uint32_t stripe = chunk % sc->stripes; /* 32bit modulus */
- chunk = chunk / sc->stripes;
+ sector_t chunk = offset >> sc->chunk_shift;
+ uint32_t stripe = do_div(chunk, sc->stripes);
 
  bio->bi_bdev = sc->stripe[stripe].dev->bdev;
  bio->bi_sector = sc->stripe[stripe].physical_start +
@@ -210,7 +209,7 @@
 
 static struct target_type stripe_target = {
  .name   = "striped",
- .version= {1, 0, 1},
+ .version= {1, 0, 2},
  .module = THIS_MODULE,
  .ctr= stripe_ctr,
  .dtr= stripe_dtr,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: device-mapper: fix TB stripe data corruption

2005-01-21 Thread Kevin Corry
On Friday 21 January 2005 2:33 pm, Benjamin LaHaise wrote:
> On Fri, Jan 21, 2005 at 06:12:03PM +, Alasdair G Kergon wrote:
> > Missing cast thought to cause data corruption on devices with stripes >
> > ~1TB.
>
> Why not make chunk a sector_t?

We have to take a mod of the chunk value and the number of stripes (which can 
be a non-power-of-2, so a shift won't work). It's been my understanding that 
you couldn't mod a 64-bit value with a 32-bit value in the kernel. Just to be 
sure, I've changed "chunk" to a sector_t and recompiled, and get the 
following error:

  MODPOST
*** Warning: "__udivdi3" [drivers/md/dm-mod.ko] undefined!
*** Warning: "__umoddi3" [drivers/md/dm-mod.ko] undefined!

-- 
Kevin Corry
[EMAIL PROTECTED]
http://evms.sourceforge.net/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/