arch/tile: warn and retry if an IPI is not accepted by the target cpu
authorChris Metcalf <cmetcalf@tilera.com>
Mon, 28 Feb 2011 18:32:14 +0000 (13:32 -0500)
committerChris Metcalf <cmetcalf@tilera.com>
Tue, 1 Mar 2011 21:20:16 +0000 (16:20 -0500)
Previously we assumed this was impossible, but in fact it can happen.
Handle it gracefully by retrying after issuing a warning.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
arch/tile/kernel/smp.c

index 9575b37..a429310 100644 (file)
@@ -36,6 +36,22 @@ static unsigned long __iomem *ipi_mappings[NR_CPUS];
 /* Set by smp_send_stop() to avoid recursive panics. */
 static int stopping_cpus;
 
+static void __send_IPI_many(HV_Recipient *recip, int nrecip, int tag)
+{
+       int sent = 0;
+       while (sent < nrecip) {
+               int rc = hv_send_message(recip, nrecip,
+                                        (HV_VirtAddr)&tag, sizeof(tag));
+               if (rc < 0) {
+                       if (!stopping_cpus)  /* avoid recursive panic */
+                               panic("hv_send_message returned %d", rc);
+                       break;
+               }
+               WARN_ONCE(rc == 0, "hv_send_message() returned zero\n");
+               sent += rc;
+       }
+}
+
 void send_IPI_single(int cpu, int tag)
 {
        HV_Recipient recip = {
@@ -43,14 +59,13 @@ void send_IPI_single(int cpu, int tag)
                .x = cpu % smp_width,
                .state = HV_TO_BE_SENT
        };
-       int rc = hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag));
-       BUG_ON(rc <= 0);
+       __send_IPI_many(&recip, 1, tag);
 }
 
 void send_IPI_many(const struct cpumask *mask, int tag)
 {
        HV_Recipient recip[NR_CPUS];
-       int cpu, sent;
+       int cpu;
        int nrecip = 0;
        int my_cpu = smp_processor_id();
        for_each_cpu(cpu, mask) {
@@ -61,17 +76,7 @@ void send_IPI_many(const struct cpumask *mask, int tag)
                r->x = cpu % smp_width;
                r->state = HV_TO_BE_SENT;
        }
-       sent = 0;
-       while (sent < nrecip) {
-               int rc = hv_send_message(recip, nrecip,
-                                        (HV_VirtAddr)&tag, sizeof(tag));
-               if (rc <= 0) {
-                       if (!stopping_cpus)  /* avoid recursive panic */
-                               panic("hv_send_message returned %d", rc);
-                       break;
-               }
-               sent += rc;
-       }
+       __send_IPI_many(recip, nrecip, tag);
 }
 
 void send_IPI_allbutself(int tag)