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: Joel Schopp <jschopp@austin.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
Родитель
28bb9ee13a
Коммит
efec959f63
|
@ -710,7 +710,12 @@ static unsigned char ibm_architecture_vec[] = {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
W(NR_CPUS), /* number of cores supported*/
|
/* 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 */
|
/* option vector 6: IBM PAPR hints */
|
||||||
4 - 2, /* length */
|
4 - 2, /* length */
|
||||||
|
@ -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)
|
static void __init prom_send_capabilities(void)
|
||||||
{
|
{
|
||||||
ihandle elfloader, root;
|
ihandle elfloader, root;
|
||||||
prom_arg_t ret;
|
prom_arg_t ret;
|
||||||
|
u32 *cores;
|
||||||
|
|
||||||
root = call_prom("open", 1, 1, ADDR("/"));
|
root = call_prom("open", 1, 1, ADDR("/"));
|
||||||
if (root != 0) {
|
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 */
|
/* try calling the ibm,client-architecture-support method */
|
||||||
prom_printf("Calling ibm,client-architecture-support...");
|
prom_printf("Calling ibm,client-architecture-support...");
|
||||||
if (call_prom_ret("call-method", 3, 2, &ret,
|
if (call_prom_ret("call-method", 3, 2, &ret,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче