Author: nwhitehorn
Date: Thu Jan  4 23:07:51 2018
New Revision: 327566
URL: https://svnweb.freebsd.org/changeset/base/327566

Log:
  Revert r327360, which can cause boot problems on high-CPU-count (>60)
  POWER8 and POWER9 systems, pending further analysis.
  
  PR:           224841

Modified:
  head/sys/powerpc/pseries/platform_chrp.c

Modified: head/sys/powerpc/pseries/platform_chrp.c
==============================================================================
--- head/sys/powerpc/pseries/platform_chrp.c    Thu Jan  4 22:59:24 2018        
(r327565)
+++ head/sys/powerpc/pseries/platform_chrp.c    Thu Jan  4 23:07:51 2018        
(r327566)
@@ -114,8 +114,6 @@ static platform_def_t chrp_platform = {
 
 PLATFORM_DEF(chrp_platform);
 
-#define BSP_MUST_BE_CPU_ZERO
-
 static int
 chrp_probe(platform_t plat)
 {
@@ -281,31 +279,13 @@ chrp_real_maxaddr(platform_t plat)
 static u_long
 chrp_timebase_freq(platform_t plat, struct cpuref *cpuref)
 {
-       char buf[8];
-       phandle_t cpu, dev, root;
-       int res;
+       phandle_t phandle;
        int32_t ticks = -1;
 
-       root = OF_peer(0);
+       phandle = cpuref->cr_hwref;
 
-       dev = OF_child(root);
-       while (dev != 0) {
-               res = OF_getprop(dev, "name", buf, sizeof(buf));
-               if (res > 0 && strcmp(buf, "cpus") == 0)
-                       break;
-               dev = OF_peer(dev);
-       }
+       OF_getencprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
 
-       for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
-               res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
-               if (res > 0 && strcmp(buf, "cpu") == 0)
-                       break;
-       }
-       if (cpu == 0)
-               return (512000000);
-
-       OF_getencprop(cpu, "timebase-frequency", &ticks, sizeof(ticks));
-
        if (ticks <= 0)
                panic("Unable to determine timebase frequency!");
 
@@ -313,11 +293,11 @@ chrp_timebase_freq(platform_t plat, struct cpuref *cpu
 }
 
 static int
-chrp_cpuref_for_server(struct cpuref *cpuref, int cpu_n, int server)
+chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
 {
        char buf[8];
        phandle_t cpu, dev, root;
-       int res, cpuid, i, j;
+       int res, cpuid;
 
        root = OF_peer(0);
 
@@ -338,84 +318,71 @@ chrp_cpuref_for_server(struct cpuref *cpuref, int cpu_
                        return (ENOENT);
        }
 
-       i = 0;
-       for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
-               res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
-               if (res <= 0 || strcmp(buf, "cpu") != 0)
-                       continue;
+       cpu = OF_child(dev);
 
-               res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
-               if (res > 0) {
-                       cell_t interrupt_servers[res/sizeof(cell_t)];
-                       OF_getencprop(cpu, "ibm,ppc-interrupt-server#s",
-                           interrupt_servers, res);
-                       for (j = 0; j < res/sizeof(cell_t); j++) {
-                               cpuid = interrupt_servers[j];
-                               if (server != -1 && cpuid == server)
-                                       break;
-                               if (cpu_n != -1 && cpu_n == i)
-                                       break;
-                               i++;
-                       }
-
-                       if (j != res/sizeof(cell_t))
-                               break;
-               } else {
-                       res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
-                       if (res <= 0)
-                               cpuid = 0;
-                       if (server != -1 && cpuid == server)
-                               break;
-                       if (cpu_n != -1 && cpu_n == i)
-                               break;
-                       i++;
-               }
+       while (cpu != 0) {
+               res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+               if (res > 0 && strcmp(buf, "cpu") == 0)
+                       break;
+               cpu = OF_peer(cpu);
        }
-
        if (cpu == 0)
                return (ENOENT);
 
-       cpuref->cr_hwref = cpuid;
-       cpuref->cr_cpuid = i;
+       cpuref->cr_hwref = cpu;
+       res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+           sizeof(cpuid));
+       if (res <= 0)
+               res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
+       if (res <= 0)
+               cpuid = 0;
+       cpuref->cr_cpuid = cpuid;
 
        return (0);
 }
 
 static int
-chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
-{
-#ifdef BSP_MUST_BE_CPU_ZERO
-       return (chrp_smp_get_bsp(plat, cpuref));
-#else
-       return (chrp_cpuref_for_server(cpuref, 0, -1));
-#endif
-}
-
-static int
 chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
 {
-#ifdef BSP_MUST_BE_CPU_ZERO
-       int bsp, ncpus, err;
-       struct cpuref scratch;
+       char buf[8];
+       phandle_t cpu;
+       int i, res, cpuid;
 
-       chrp_smp_get_bsp(plat, &scratch);
-       chrp_cpuref_for_server(&scratch, -1, scratch.cr_hwref);
-       bsp = scratch.cr_cpuid;
+       /* Check for whether it should be the next thread */
+       res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s");
+       if (res > 0) {
+               cell_t interrupt_servers[res/sizeof(cell_t)];
+               OF_getencprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
+                   interrupt_servers, res);
+               for (i = 0; i < res/sizeof(cell_t) - 1; i++) {
+                       if (interrupt_servers[i] == cpuref->cr_cpuid) {
+                               cpuref->cr_cpuid = interrupt_servers[i+1];
+                               return (0);
+                       }
+               }
+       }
 
-       for (ncpus = bsp; chrp_cpuref_for_server(&scratch, ncpus, -1) !=
-           ENOENT; ncpus++) {}
-       if (cpuref->cr_cpuid + 1 == ncpus)
+       /* Next CPU core/package */
+       cpu = OF_peer(cpuref->cr_hwref);
+       while (cpu != 0) {
+               res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+               if (res > 0 && strcmp(buf, "cpu") == 0)
+                       break;
+               cpu = OF_peer(cpu);
+       }
+       if (cpu == 0)
                return (ENOENT);
-       err = chrp_cpuref_for_server(cpuref,
-           (cpuref->cr_cpuid + bsp + 1) % ncpus, -1);
-       if (cpuref->cr_cpuid >= bsp)
-               cpuref->cr_cpuid -= bsp;
-       else
-               cpuref->cr_cpuid = ncpus - (bsp - cpuref->cr_cpuid);
-       return (err);
-#else
-       return (chrp_cpuref_for_server(cpuref, cpuref->cr_cpuid+1, -1));
-#endif
+
+       cpuref->cr_hwref = cpu;
+       res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+           sizeof(cpuid));
+       if (res <= 0)
+               res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
+       if (res <= 0)
+               cpuid = 0;
+       cpuref->cr_cpuid = cpuid;
+
+       return (0);
 }
 
 static int
@@ -436,17 +403,14 @@ chrp_smp_get_bsp(platform_t plat, struct cpuref *cpure
        bsp = OF_instance_to_package(inst);
 
        /* Pick the primary thread. Can it be any other? */
+       cpuref->cr_hwref = bsp;
        res = OF_getencprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid,
            sizeof(cpuid));
        if (res <= 0)
                res = OF_getencprop(bsp, "reg", &cpuid, sizeof(cpuid));
        if (res <= 0)
                cpuid = 0;
-
-       chrp_cpuref_for_server(cpuref, -1, cpuid);
-#ifdef BSP_MUST_BE_CPU_ZERO
        cpuref->cr_cpuid = cpuid;
-#endif
 
        return (0);
 }
@@ -474,7 +438,7 @@ chrp_smp_start_cpu(platform_t plat, struct pcpu *pc)
        ap_pcpu = pc;
        powerpc_sync();
 
-       result = rtas_call_method(start_cpu, 3, 1, pc->pc_hwref, EXC_RST, pc,
+       result = rtas_call_method(start_cpu, 3, 1, pc->pc_cpuid, EXC_RST, pc,
            &err);
        if (result < 0 || err != 0) {
                printf("RTAS error (%d/%d): unable to start AP %d\n",
@@ -492,62 +456,39 @@ chrp_smp_start_cpu(platform_t plat, struct pcpu *pc)
 static struct cpu_group *
 chrp_smp_topo(platform_t plat)
 {
-       char buf[8];
-       phandle_t cpu, dev, root;
-       int res, nthreads;
+       struct pcpu *pc, *last_pc;
+       int i, ncores, ncpus;
 
-       root = OF_peer(0);
-
-       dev = OF_child(root);
-       while (dev != 0) {
-               res = OF_getprop(dev, "name", buf, sizeof(buf));
-               if (res > 0 && strcmp(buf, "cpus") == 0)
-                       break;
-               dev = OF_peer(dev);
-       }
-
-       nthreads = 1;
-       for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
-               res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
-               if (res <= 0 || strcmp(buf, "cpu") != 0)
+       ncores = ncpus = 0;
+       last_pc = NULL;
+       for (i = 0; i <= mp_maxid; i++) {
+               pc = pcpu_find(i);
+               if (pc == NULL)
                        continue;
-
-               res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
-
-               if (res >= 0)
-                       nthreads = res / sizeof(cell_t);
-               else
-                       nthreads = 1;
-               break;
+               if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref)
+                       ncores++;
+               last_pc = pc;
+               ncpus++;
        }
 
-       if (mp_ncpus % nthreads != 0) {
+       if (ncpus % ncores != 0) {
                printf("WARNING: Irregular SMP topology. Performance may be "
-                    "suboptimal (%d threads, %d on first core)\n",
-                    mp_ncpus, nthreads);
+                    "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores);
                return (smp_topo_none());
        }
 
        /* Don't do anything fancier for non-threaded SMP */
-       if (nthreads == 1)
+       if (ncpus == ncores)
                return (smp_topo_none());
 
-       return (smp_topo_1level(CG_SHARE_L1, nthreads, CG_FLAG_SMT));
+       return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT));
 }
 #endif
 
 static void
 chrp_reset(platform_t platform)
 {
-       cell_t token, status;
-
-       if (rtas_exists()) {
-               token = rtas_token_lookup("system-reboot");
-               if (token != -1)
-                       rtas_call_method(token, 0, 1, &status);
-       } else {
-               OF_reboot();
-       }
+       OF_reboot();
 }
 
 #ifdef __powerpc64__
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to