On 14-07-09 01:26 PM, Charlie Paul wrote:
From: John Jacques <john.jacq...@lsi.com>

When we do a reset (core, not chip or system), the core that is doing the reset 
has to
tell all the other cores to reset.  To do this, we call 
smp_call_function_single().
In this case the function specified in smp_call_function_single() doesn't 
return.
The "wait" parameter (third argument, described as '@wait: If true, wait until
function has completed on other CPUs.') doesn't work as described without the 
patch.

Without the patch, smp_call_function_single() doesn't return when the function
indicated resets the called core.  The comments indicate that it should, but it 
does not.

Signen-off-by: John Jacques <john.jacq...@lsi.com>
---
  kernel/smp.c |   24 +++++++++++++++++++-----
  1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/kernel/smp.c b/kernel/smp.c
index d5f3238..040b2b1 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -17,14 +17,14 @@
  static struct {
        struct list_head        queue;
        raw_spinlock_t          lock;
-} call_function __cacheline_aligned_in_smp =
-       {
+} call_function __cacheline_aligned_in_smp = {
                .queue          = LIST_HEAD_INIT(call_function.queue),
                .lock           = __RAW_SPIN_LOCK_UNLOCKED(call_function.lock),
        };

  enum {
        CSD_FLAG_LOCK           = 0x01,
+       CSD_FLAG_NOWAIT         = 0x02,
  };

  struct call_function_data {
@@ -268,6 +268,8 @@ void generic_smp_call_function_single_interrupt(void)

        while (!list_empty(&list)) {
                struct call_single_data *data;
+               void (*func)(void *);
+               void *info;

                data = list_entry(list.next, struct call_single_data, list);
                list_del(&data->list);
@@ -278,12 +280,21 @@ void generic_smp_call_function_single_interrupt(void)
                 * so save them away before making the call:
                 */
                data_flags = data->flags;
-
-               data->func(data->info);
+               func = data->func;
+               info = data->info;

                /*
+                * Unlock before calling func so that func never has
+                * to return.
+                *
                 * Unlocked CSDs are valid through generic_exec_single():
                 */
+               if ((data_flags & CSD_FLAG_LOCK) &&
+                   (data_flags & CSD_FLAG_NOWAIT))
+                       csd_unlock(data);
+
+               func(info);
+
                if (data_flags & CSD_FLAG_LOCK)
                        csd_unlock(data);
        }
@@ -337,6 +348,9 @@ int smp_call_function_single(int cpu, smp_call_func_t func, 
void *info,

                        csd_lock(data);

+                       if (!wait)
+                               data->flags |= CSD_FLAG_NOWAIT;
+
                        data->func = func;
                        data->info = info;
                        generic_exec_single(cpu, data, wait);
@@ -672,7 +686,7 @@ EXPORT_SYMBOL(nr_cpu_ids);
  /* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
  void __init setup_nr_cpu_ids(void)
  {
-       nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
+       nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask), NR_CPUS) + 
1;

I had some structural comments about this patch, that aren't addressed. The rest of the series looks ok though.

Bruce

  }

  /* Called by boot processor to activate the rest. */


--
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to