MIPS: OCTEON: Extend number of supported CPUs past 32
authorDavid Daney <david.daney@cavium.com>
Tue, 2 Feb 2016 01:46:54 +0000 (17:46 -0800)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 13 May 2016 12:01:39 +0000 (14:01 +0200)
To support more than 48 CPUs, the bootinfo structure grows a new
coremask structure.  Add the definition of the structure and add it to
struct cvmx_bootinfo.  In prom_init(), copy the new coremask data into
the sysinfo structure, and use it in smp_setup().

Signed-off-by: David Daney <david.daney@cavium.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12319/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/cavium-octeon/setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/include/asm/octeon/cvmx-bootinfo.h
arch/mips/include/asm/octeon/cvmx-coremask.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-sysinfo.h

index cd7101f..9c6ad2f 100644 (file)
@@ -637,9 +637,22 @@ void __init prom_init(void)
        sysinfo = cvmx_sysinfo_get();
        memset(sysinfo, 0, sizeof(*sysinfo));
        sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20;
-       sysinfo->phy_mem_desc_ptr =
-               cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr);
-       sysinfo->core_mask = octeon_bootinfo->core_mask;
+       sysinfo->phy_mem_desc_addr = (u64)phys_to_virt(octeon_bootinfo->phy_mem_desc_addr);
+
+       if ((octeon_bootinfo->major_version > 1) ||
+           (octeon_bootinfo->major_version == 1 &&
+            octeon_bootinfo->minor_version >= 4))
+               cvmx_coremask_copy(&sysinfo->core_mask,
+                                  &octeon_bootinfo->ext_core_mask);
+       else
+               cvmx_coremask_set64(&sysinfo->core_mask,
+                                   octeon_bootinfo->core_mask);
+
+       /* Some broken u-boot pass garbage in upper bits, clear them out */
+       if (!OCTEON_IS_MODEL(OCTEON_CN78XX))
+               for (i = 512; i < 1024; i++)
+                       cvmx_coremask_clear_core(&sysinfo->core_mask, i);
+
        sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr;
        sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz;
        sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2;
index 61a60e4..42395c5 100644 (file)
@@ -103,6 +103,8 @@ static void octeon_smp_setup(void)
        int cpus;
        int id;
        int core_mask = octeon_get_boot_coremask();
+       struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get();
+
 #ifdef CONFIG_HOTPLUG_CPU
        unsigned int num_cores = cvmx_octeon_num_cores();
 #endif
@@ -119,7 +121,7 @@ static void octeon_smp_setup(void)
        /* The present CPUs get the lowest CPU numbers. */
        cpus = 1;
        for (id = 0; id < NR_CPUS; id++) {
-               if ((id != coreid) && (core_mask & (1 << id))) {
+               if ((id != coreid) && cvmx_coremask_is_core_set(&sysinfo->core_mask, id)) {
                        set_cpu_possible(cpus, true);
                        set_cpu_present(cpus, true);
                        __cpu_number_map[id] = cpus;
index d92cf59..c455d34 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef __CVMX_BOOTINFO_H__
 #define __CVMX_BOOTINFO_H__
 
+#include "cvmx-coremask.h"
+
 /*
  * Current major and minor versions of the CVMX bootinfo block that is
  * passed from the bootloader to the application.  This is versioned
@@ -39,7 +41,7 @@
  * versions.
  */
 #define CVMX_BOOTINFO_MAJ_VER 1
-#define CVMX_BOOTINFO_MIN_VER 3
+#define CVMX_BOOTINFO_MIN_VER 4
 
 #if (CVMX_BOOTINFO_MAJ_VER == 1)
 #define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20
@@ -124,6 +126,13 @@ struct cvmx_bootinfo {
         */
        uint64_t fdt_addr;
 #endif
+#if (CVMX_BOOTINFO_MIN_VER >= 4)
+       /*
+        * Coremask used for processors with more than 32 cores
+        * or with OCI.  This replaces core_mask.
+        */
+       struct cvmx_coremask ext_core_mask;
+#endif
 #else                          /* __BIG_ENDIAN */
        /*
         * Little-Endian: When the CPU mode is switched to
@@ -177,6 +186,9 @@ struct cvmx_bootinfo {
 #if (CVMX_BOOTINFO_MIN_VER >= 3)
        uint64_t fdt_addr;
 #endif
+#if (CVMX_BOOTINFO_MIN_VER >= 4)
+       struct cvmx_coremask ext_core_mask;
+#endif
 #endif
 };
 
diff --git a/arch/mips/include/asm/octeon/cvmx-coremask.h b/arch/mips/include/asm/octeon/cvmx-coremask.h
new file mode 100644 (file)
index 0000000..097dc09
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2016  Cavium Inc. (support@cavium.com).
+ *
+ */
+
+/*
+ * Module to support operations on bitmap of cores. Coremask can be used to
+ * select a specific core, a group of cores, or all available cores, for
+ * initialization and differentiation of roles within a single shared binary
+ * executable image.
+ *
+ * The core numbers used in this file are the same value as what is found in
+ * the COP0_EBASE register and the rdhwr 0 instruction.
+ *
+ * For the CN78XX and other multi-node environments the core numbers are not
+ * contiguous.  The core numbers for the CN78XX are as follows:
+ *
+ * Node 0:     Cores 0 - 47
+ * Node 1:     Cores 128 - 175
+ * Node 2:     Cores 256 - 303
+ * Node 3:     Cores 384 - 431
+ *
+ */
+
+#ifndef __CVMX_COREMASK_H__
+#define __CVMX_COREMASK_H__
+
+#define CVMX_MIPS_MAX_CORES 1024
+/* bits per holder */
+#define CVMX_COREMASK_ELTSZ 64
+
+/* cvmx_coremask_t's size in u64 */
+#define CVMX_COREMASK_BMPSZ (CVMX_MIPS_MAX_CORES / CVMX_COREMASK_ELTSZ)
+
+
+/* cvmx_coremask_t */
+struct cvmx_coremask {
+       u64 coremask_bitmap[CVMX_COREMASK_BMPSZ];
+};
+
+/*
+ * Is ``core'' set in the coremask?
+ */
+static inline bool cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm,
+                                           int core)
+{
+       int n, i;
+
+       n = core % CVMX_COREMASK_ELTSZ;
+       i = core / CVMX_COREMASK_ELTSZ;
+
+       return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0;
+}
+
+/*
+ * Make a copy of a coremask
+ */
+static inline void cvmx_coremask_copy(struct cvmx_coremask *dest,
+                                     const struct cvmx_coremask *src)
+{
+       memcpy(dest, src, sizeof(*dest));
+}
+
+/*
+ * Set the lower 64-bit of the coremask.
+ */
+static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm,
+                                      uint64_t coremask_64)
+{
+       pcm->coremask_bitmap[0] = coremask_64;
+}
+
+/*
+ * Clear ``core'' from the coremask.
+ */
+static inline void cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core)
+{
+       int n, i;
+
+       n = core % CVMX_COREMASK_ELTSZ;
+       i = core / CVMX_COREMASK_ELTSZ;
+       pcm->coremask_bitmap[i] &= ~(1ull << n);
+}
+
+#endif /* __CVMX_COREMASK_H__ */
index 78cd64a..c6c3ee3 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef __CVMX_SYSINFO_H__
 #define __CVMX_SYSINFO_H__
 
+#include "cvmx-coremask.h"
+
 #define OCTEON_SERIAL_LEN 20
 /**
  * Structure describing application specific information.
@@ -50,8 +52,7 @@ struct cvmx_sysinfo {
        uint64_t system_dram_size;
 
        /* ptr to memory descriptor block */
-       void *phy_mem_desc_ptr;
-
+       uint64_t phy_mem_desc_addr;
 
        /* Application image specific variables */
        /* stack top address (virtual) */
@@ -63,7 +64,7 @@ struct cvmx_sysinfo {
        /* heap size in bytes */
        uint32_t heap_size;
        /* coremask defining cores running application */
-       uint32_t core_mask;
+       struct cvmx_coremask core_mask;
        /* Deprecated, use cvmx_coremask_first_core() to select init core */
        uint32_t init_core;