Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efec959f authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

powerpc/pseries: Pass more accurate number of supported cores to firmware



Updated variant of a patch by Joel Schopp.

The field containing the number of supported cores which we pass to
firmware via the ibm,client-architecture call was set by a previous
patch statically as high as is possible (NR_CPUS).

However, that value isn't quite right for a system that supports
multiple threads per core, thus permitting the firmware to assign
more cores to a Linux partition than it can really cope with.

This patch improves it by using the device-tree to determine the
number of threads supported by the processors in order to adjust
the value passed to firmware.

Signed-off-by: default avatarJoel Schopp <jschopp@austin.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 28bb9ee1
Loading
Loading
Loading
Loading
+63 −1
Original line number Diff line number Diff line
@@ -710,6 +710,11 @@ static unsigned char ibm_architecture_vec[] = {
	0,
	0,
	0,
	/* WARNING: The offset of the "number of cores" field below
	 * must match by the macro below. Update the definition if
	 * the structure layout changes.
	 */
#define IBM_ARCH_VEC_NRCORES_OFFSET	100
	W(NR_CPUS),			/* number of cores supported */

	/* option vector 6: IBM PAPR hints */
@@ -807,13 +812,70 @@ static struct fake_elf {
	}
};

static int __init prom_count_smt_threads(void)
{
	phandle node;
	char type[64];
	unsigned int plen;

	/* Pick up th first CPU node we can find */
	for (node = 0; prom_next_node(&node); ) {
		type[0] = 0;
		prom_getprop(node, "device_type", type, sizeof(type));

		if (strcmp(type, RELOC("cpu")))
			continue;
		/*
		 * There is an entry for each smt thread, each entry being
		 * 4 bytes long.  All cpus should have the same number of
		 * smt threads, so return after finding the first.
		 */
		plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
		if (plen == PROM_ERROR)
			break;
		plen >>= 2;
		prom_debug("Found 0x%x smt threads per core\n", (unsigned long)plen);

		/* Sanity check */
		if (plen < 1 || plen > 64) {
			prom_printf("Threads per core 0x%x out of bounds, assuming 1\n",
				    (unsigned long)plen);
			return 1;
		}
		return plen;
	}
	prom_debug("No threads found, assuming 1 per core\n");

	return 1;

}


static void __init prom_send_capabilities(void)
{
	ihandle elfloader, root;
	prom_arg_t ret;
	u32 *cores;

	root = call_prom("open", 1, 1, ADDR("/"));
	if (root != 0) {
		/* We need to tell the FW about the number of cores we support.
		 *
		 * To do that, we count the number of threads on the first core
		 * (we assume this is the same for all cores) and use it to
		 * divide NR_CPUS.
		 */
		cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]);
		if (*cores != NR_CPUS) {
			prom_printf("WARNING ! "
				    "ibm_architecture_vec structure inconsistent: 0x%x !\n",
				    *cores);
		} else {
			*cores = NR_CPUS / prom_count_smt_threads();
			prom_printf("Max number of cores passed to firmware: 0x%x\n",
				    (unsigned long)*cores);
		}

		/* try calling the ibm,client-architecture-support method */
		prom_printf("Calling ibm,client-architecture-support...");
		if (call_prom_ret("call-method", 3, 2, &ret,