1
0
Fork 0

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: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
hifive-unleashed-5.1
Nathan Fontenot 2013-04-24 05:57:18 +00:00 committed by Benjamin Herrenschmidt
parent 43c0ea6053
commit f0ff7eb483
6 changed files with 111 additions and 55 deletions

View File

@ -50,6 +50,7 @@
#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000)
#define FW_FEATURE_SET_MODE ASM_CONST(0x0000000040000000)
#define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000)
#define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
#ifndef __ASSEMBLY__
@ -64,7 +65,8 @@ enum {
FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
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_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
FW_FEATURE_POWERNV_ALWAYS = 0,

View File

@ -110,31 +110,28 @@ struct of_drconf_cell {
/* Option vector 4: IBM PAPR implementation */
#define OV4_MIN_ENT_CAP 0x01 /* minimum VP entitled capacity */
/* Option vector 5: PAPR/OF options supported */
#define OV5_LPAR 0x80 /* logical partitioning supported */
#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */
/* Option vector 5: PAPR/OF options supported
* These bits are also used in firmware_has_feature() to validate
* 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 */
#define OV5_DRCONF_MEMORY 0x20
#define OV5_LARGE_PAGES 0x10 /* large pages supported */
#define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */
/* PCIe/MSI support. Without MSI full PCIe is not supported */
#ifdef CONFIG_PCI_MSI
#define OV5_MSI 0x01 /* PCIe/MSI support */
#else
#define OV5_MSI 0x00
#endif /* CONFIG_PCI_MSI */
#ifdef CONFIG_PPC_SMLPAR
#define OV5_CMO 0x80 /* Cooperative Memory Overcommitment */
#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 */
#define OV5_DRCONF_MEMORY 0x0220
#define OV5_LARGE_PAGES 0x0210 /* large pages supported */
#define OV5_DONATE_DEDICATE_CPU 0x0202 /* donate dedicated CPU support */
#define OV5_MSI 0x0201 /* PCIe/MSI support */
#define OV5_CMO 0x0480 /* Cooperative Memory Overcommitment */
#define OV5_XCMO 0x0440 /* Page Coalescing */
#define OV5_TYPE1_AFFINITY 0x0580 /* Type 1 NUMA affinity */
#define OV5_PFO_HW_RNG 0x0E80 /* PFO Random Number Generator */
#define OV5_PFO_HW_842 0x0E40 /* PFO Compression Accelerator */
#define OV5_PFO_HW_ENCR 0x0E20 /* PFO Encryption Accelerator */
#define OV5_SUB_PROCESSORS 0x0F01 /* 1,2,or 4 Sub-Processors supported */
/* Option Vector 6: IBM PAPR hints */
#define OV6_LINUX 0x02 /* Linux is our OS */

View File

@ -684,11 +684,21 @@ unsigned char ibm_architecture_vec[] = {
/* option vector 5: PAPR/OF options */
19 - 2, /* length */
0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
OV5_DONATE_DEDICATE_CPU | OV5_MSI,
OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
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,
OV5_CMO | OV5_XCMO,
OV5_TYPE1_AFFINITY,
#endif
0,
#ifdef CONFIG_PPC_SMLPAR
OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
#else
0,
#endif
OV5_FEAT(OV5_TYPE1_AFFINITY),
0,
0,
0,
@ -702,8 +712,9 @@ unsigned char ibm_architecture_vec[] = {
0,
0,
0,
OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR | OV5_PFO_HW_842,
OV5_SUB_PROCESSORS,
OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
OV5_FEAT(OV5_PFO_HW_842),
OV5_FEAT(OV5_SUB_PROCESSORS),
/* option vector 6: IBM PAPR hints */
4 - 2, /* length */
0,

View File

@ -28,18 +28,18 @@
#include "pseries.h"
typedef struct {
struct hypertas_fw_feature {
unsigned long val;
char * name;
} firmware_feature_t;
};
/*
* 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
* string must match.
*/
static __initdata firmware_feature_t
firmware_features_table[] = {
static __initdata struct hypertas_fw_feature
hypertas_fw_features_table[] = {
{FW_FEATURE_PFT, "hcall-pft"},
{FW_FEATURE_TCE, "hcall-tce"},
{FW_FEATURE_SPRG0, "hcall-sprg0"},
@ -69,16 +69,16 @@ firmware_features_table[] = {
* device-tree/ibm,hypertas-functions. Ultimately this functionality may
* 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;
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 (i = 0; i < ARRAY_SIZE(firmware_features_table); i++) {
const char *name = firmware_features_table[i].name;
for (i = 0; i < ARRAY_SIZE(hypertas_fw_features_table); i++) {
const char *name = hypertas_fw_features_table[i].name;
size_t size;
/*
@ -94,10 +94,39 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
/* we have a match */
powerpc_firmware_features |=
firmware_features_table[i].val;
hypertas_fw_features_table[i].val;
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");
}

View File

@ -19,7 +19,10 @@ extern void request_event_sources_irqs(struct device_node *np,
#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;

View File

@ -628,25 +628,39 @@ static void __init pSeries_init_early(void)
* Called very early, MMU is off, device-tree isn't unflattened
*/
static int __init pSeries_probe_hypertas(unsigned long node,
const char *uname, int depth,
void *data)
static int __init pseries_probe_fw_features(unsigned long node,
const char *uname, int depth,
void *data)
{
const char *hypertas;
const char *prop;
unsigned long len;
static int hypertas_found;
static int vec5_found;
if (depth != 1 ||
(strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0))
if (depth != 1)
return 0;
hypertas = of_get_flat_dt_prop(node, "ibm,hypertas-functions", &len);
if (!hypertas)
return 1;
if (!strcmp(uname, "rtas") || !strcmp(uname, "rtas@0")) {
prop = of_get_flat_dt_prop(node, "ibm,hypertas-functions",
&len);
if (prop) {
powerpc_firmware_features |= FW_FEATURE_LPAR;
fw_hypertas_feature_init(prop, len);
}
powerpc_firmware_features |= FW_FEATURE_LPAR;
fw_feature_init(hypertas, len);
hypertas_found = 1;
}
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)
@ -669,7 +683,7 @@ static int __init pSeries_probe(void)
pr_debug("pSeries detected, looking for LPAR capability...\n");
/* 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))
hpte_init_lpar();