Commit f0ff7eb4 authored by Nathan Fontenot's avatar Nathan Fontenot Committed by Benjamin Herrenschmidt

powerpc/pseries: Update firmware_has_feature() to check architecture vector 5 bits

The firmware_has_feature() function makes it easy to check for supported
features of the hypervisor. This patch extends the capability of
firmware_has_feature() to include checking for specified bits
in vector 5 of the architecture vector as reported in the device tree.

As part of this the #defines used for the architecture vector are re-defined
such that each option has the index into vector 5 and the feature bit encoded
into it. This makes checking for architecture bits when initiating data
for firmware_has_feature much easier.
Signed-off-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 43c0ea60
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000) #define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000)
#define FW_FEATURE_SET_MODE ASM_CONST(0x0000000040000000) #define FW_FEATURE_SET_MODE ASM_CONST(0x0000000040000000)
#define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000) #define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000)
#define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -64,7 +65,8 @@ enum { ...@@ -64,7 +65,8 @@ enum {
FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR | FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO | FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO |
FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY, FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY |
FW_FEATURE_TYPE1_AFFINITY,
FW_FEATURE_PSERIES_ALWAYS = 0, FW_FEATURE_PSERIES_ALWAYS = 0,
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2, FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
FW_FEATURE_POWERNV_ALWAYS = 0, FW_FEATURE_POWERNV_ALWAYS = 0,
......
...@@ -110,31 +110,28 @@ struct of_drconf_cell { ...@@ -110,31 +110,28 @@ struct of_drconf_cell {
/* Option vector 4: IBM PAPR implementation */ /* Option vector 4: IBM PAPR implementation */
#define OV4_MIN_ENT_CAP 0x01 /* minimum VP entitled capacity */ #define OV4_MIN_ENT_CAP 0x01 /* minimum VP entitled capacity */
/* Option vector 5: PAPR/OF options supported */ /* Option vector 5: PAPR/OF options supported
#define OV5_LPAR 0x80 /* logical partitioning supported */ * These bits are also used in firmware_has_feature() to validate
#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */ * the capabilities reported for vector 5 in the device tree so we
* encode the vector index in the define and use the OV5_FEAT()
* and OV5_INDX() macros to extract the desired information.
*/
#define OV5_FEAT(x) ((x) & 0xff)
#define OV5_INDX(x) ((x) >> 8)
#define OV5_LPAR 0x0280 /* logical partitioning supported */
#define OV5_SPLPAR 0x0240 /* shared-processor LPAR supported */
/* ibm,dynamic-reconfiguration-memory property supported */ /* ibm,dynamic-reconfiguration-memory property supported */
#define OV5_DRCONF_MEMORY 0x20 #define OV5_DRCONF_MEMORY 0x0220
#define OV5_LARGE_PAGES 0x10 /* large pages supported */ #define OV5_LARGE_PAGES 0x0210 /* large pages supported */
#define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */ #define OV5_DONATE_DEDICATE_CPU 0x0202 /* donate dedicated CPU support */
/* PCIe/MSI support. Without MSI full PCIe is not supported */ #define OV5_MSI 0x0201 /* PCIe/MSI support */
#ifdef CONFIG_PCI_MSI #define OV5_CMO 0x0480 /* Cooperative Memory Overcommitment */
#define OV5_MSI 0x01 /* PCIe/MSI support */ #define OV5_XCMO 0x0440 /* Page Coalescing */
#else #define OV5_TYPE1_AFFINITY 0x0580 /* Type 1 NUMA affinity */
#define OV5_MSI 0x00 #define OV5_PFO_HW_RNG 0x0E80 /* PFO Random Number Generator */
#endif /* CONFIG_PCI_MSI */ #define OV5_PFO_HW_842 0x0E40 /* PFO Compression Accelerator */
#ifdef CONFIG_PPC_SMLPAR #define OV5_PFO_HW_ENCR 0x0E20 /* PFO Encryption Accelerator */
#define OV5_CMO 0x80 /* Cooperative Memory Overcommitment */ #define OV5_SUB_PROCESSORS 0x0F01 /* 1,2,or 4 Sub-Processors supported */
#define OV5_XCMO 0x40 /* Page Coalescing */
#else
#define OV5_CMO 0x00
#define OV5_XCMO 0x00
#endif
#define OV5_TYPE1_AFFINITY 0x80 /* Type 1 NUMA affinity */
#define OV5_PFO_HW_RNG 0x80 /* PFO Random Number Generator */
#define OV5_PFO_HW_842 0x40 /* PFO Compression Accelerator */
#define OV5_PFO_HW_ENCR 0x20 /* PFO Encryption Accelerator */
#define OV5_SUB_PROCESSORS 0x01 /* 1,2,or 4 Sub-Processors supported */
/* Option Vector 6: IBM PAPR hints */ /* Option Vector 6: IBM PAPR hints */
#define OV6_LINUX 0x02 /* Linux is our OS */ #define OV6_LINUX 0x02 /* Linux is our OS */
......
...@@ -684,11 +684,21 @@ unsigned char ibm_architecture_vec[] = { ...@@ -684,11 +684,21 @@ unsigned char ibm_architecture_vec[] = {
/* option vector 5: PAPR/OF options */ /* option vector 5: PAPR/OF options */
19 - 2, /* length */ 19 - 2, /* length */
0, /* don't ignore, don't halt */ 0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
OV5_DONATE_DEDICATE_CPU | OV5_MSI, OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
#ifdef CONFIG_PCI_MSI
/* PCIe/MSI support. Without MSI full PCIe is not supported */
OV5_FEAT(OV5_MSI),
#else
0,
#endif
0, 0,
OV5_CMO | OV5_XCMO, #ifdef CONFIG_PPC_SMLPAR
OV5_TYPE1_AFFINITY, OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
#else
0,
#endif
OV5_FEAT(OV5_TYPE1_AFFINITY),
0, 0,
0, 0,
0, 0,
...@@ -702,8 +712,9 @@ unsigned char ibm_architecture_vec[] = { ...@@ -702,8 +712,9 @@ unsigned char ibm_architecture_vec[] = {
0, 0,
0, 0,
0, 0,
OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR | OV5_PFO_HW_842, OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
OV5_SUB_PROCESSORS, OV5_FEAT(OV5_PFO_HW_842),
OV5_FEAT(OV5_SUB_PROCESSORS),
/* option vector 6: IBM PAPR hints */ /* option vector 6: IBM PAPR hints */
4 - 2, /* length */ 4 - 2, /* length */
0, 0,
......
...@@ -28,18 +28,18 @@ ...@@ -28,18 +28,18 @@
#include "pseries.h" #include "pseries.h"
typedef struct { struct hypertas_fw_feature {
unsigned long val; unsigned long val;
char * name; char * name;
} firmware_feature_t; };
/* /*
* The names in this table match names in rtas/ibm,hypertas-functions. If the * The names in this table match names in rtas/ibm,hypertas-functions. If the
* entry ends in a '*', only upto the '*' is matched. Otherwise the entire * entry ends in a '*', only upto the '*' is matched. Otherwise the entire
* string must match. * string must match.
*/ */
static __initdata firmware_feature_t static __initdata struct hypertas_fw_feature
firmware_features_table[] = { hypertas_fw_features_table[] = {
{FW_FEATURE_PFT, "hcall-pft"}, {FW_FEATURE_PFT, "hcall-pft"},
{FW_FEATURE_TCE, "hcall-tce"}, {FW_FEATURE_TCE, "hcall-tce"},
{FW_FEATURE_SPRG0, "hcall-sprg0"}, {FW_FEATURE_SPRG0, "hcall-sprg0"},
...@@ -69,16 +69,16 @@ firmware_features_table[] = { ...@@ -69,16 +69,16 @@ firmware_features_table[] = {
* device-tree/ibm,hypertas-functions. Ultimately this functionality may * device-tree/ibm,hypertas-functions. Ultimately this functionality may
* be moved into prom.c prom_init(). * be moved into prom.c prom_init().
*/ */
void __init fw_feature_init(const char *hypertas, unsigned long len) void __init fw_hypertas_feature_init(const char *hypertas, unsigned long len)
{ {
const char *s; const char *s;
int i; int i;
pr_debug(" -> fw_feature_init()\n"); pr_debug(" -> fw_hypertas_feature_init()\n");
for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
for (i = 0; i < ARRAY_SIZE(firmware_features_table); i++) { for (i = 0; i < ARRAY_SIZE(hypertas_fw_features_table); i++) {
const char *name = firmware_features_table[i].name; const char *name = hypertas_fw_features_table[i].name;
size_t size; size_t size;
/* /*
...@@ -94,10 +94,39 @@ void __init fw_feature_init(const char *hypertas, unsigned long len) ...@@ -94,10 +94,39 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
/* we have a match */ /* we have a match */
powerpc_firmware_features |= powerpc_firmware_features |=
firmware_features_table[i].val; hypertas_fw_features_table[i].val;
break; break;
} }
} }
pr_debug(" <- fw_feature_init()\n"); pr_debug(" <- fw_hypertas_feature_init()\n");
}
struct vec5_fw_feature {
unsigned long val;
unsigned int feature;
};
static __initdata struct vec5_fw_feature
vec5_fw_features_table[] = {
{FW_FEATURE_TYPE1_AFFINITY, OV5_TYPE1_AFFINITY},
};
void __init fw_vec5_feature_init(const char *vec5, unsigned long len)
{
unsigned int index, feat;
int i;
pr_debug(" -> fw_vec5_feature_init()\n");
for (i = 0; i < ARRAY_SIZE(vec5_fw_features_table); i++) {
index = OV5_INDX(vec5_fw_features_table[i].feature);
feat = OV5_FEAT(vec5_fw_features_table[i].feature);
if (vec5[index] & feat)
powerpc_firmware_features |=
vec5_fw_features_table[i].val;
}
pr_debug(" <- fw_vec5_feature_init()\n");
} }
...@@ -19,7 +19,10 @@ extern void request_event_sources_irqs(struct device_node *np, ...@@ -19,7 +19,10 @@ extern void request_event_sources_irqs(struct device_node *np,
#include <linux/of.h> #include <linux/of.h>
extern void __init fw_feature_init(const char *hypertas, unsigned long len); extern void __init fw_hypertas_feature_init(const char *hypertas,
unsigned long len);
extern void __init fw_vec5_feature_init(const char *hypertas,
unsigned long len);
struct pt_regs; struct pt_regs;
......
...@@ -628,25 +628,39 @@ static void __init pSeries_init_early(void) ...@@ -628,25 +628,39 @@ static void __init pSeries_init_early(void)
* Called very early, MMU is off, device-tree isn't unflattened * Called very early, MMU is off, device-tree isn't unflattened
*/ */
static int __init pSeries_probe_hypertas(unsigned long node, static int __init pseries_probe_fw_features(unsigned long node,
const char *uname, int depth, const char *uname, int depth,
void *data) void *data)
{ {
const char *hypertas; const char *prop;
unsigned long len; unsigned long len;
static int hypertas_found;
static int vec5_found;
if (depth != 1 || if (depth != 1)
(strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0))
return 0; return 0;
hypertas = of_get_flat_dt_prop(node, "ibm,hypertas-functions", &len); if (!strcmp(uname, "rtas") || !strcmp(uname, "rtas@0")) {
if (!hypertas) prop = of_get_flat_dt_prop(node, "ibm,hypertas-functions",
return 1; &len);
if (prop) {
powerpc_firmware_features |= FW_FEATURE_LPAR;
fw_hypertas_feature_init(prop, len);
}
powerpc_firmware_features |= FW_FEATURE_LPAR; hypertas_found = 1;
fw_feature_init(hypertas, len); }
return 1; if (!strcmp(uname, "chosen")) {
prop = of_get_flat_dt_prop(node, "ibm,architecture-vec-5",
&len);
if (prop)
fw_vec5_feature_init(prop, len);
vec5_found = 1;
}
return hypertas_found && vec5_found;
} }
static int __init pSeries_probe(void) static int __init pSeries_probe(void)
...@@ -669,7 +683,7 @@ static int __init pSeries_probe(void) ...@@ -669,7 +683,7 @@ static int __init pSeries_probe(void)
pr_debug("pSeries detected, looking for LPAR capability...\n"); pr_debug("pSeries detected, looking for LPAR capability...\n");
/* Now try to figure out if we are running on LPAR */ /* Now try to figure out if we are running on LPAR */
of_scan_flat_dt(pSeries_probe_hypertas, NULL); of_scan_flat_dt(pseries_probe_fw_features, NULL);
if (firmware_has_feature(FW_FEATURE_LPAR)) if (firmware_has_feature(FW_FEATURE_LPAR))
hpte_init_lpar(); hpte_init_lpar();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment