[PATCH 08/10] powerpc/xive: take into account '/ibm, plat-res-int-priorities'
Cédric Le Goater
clg at kaod.org
Tue Aug 8 18:56:18 AEST 2017
'/ibm,plat-res-int-priorities' contains a list of priorities that the
hypervisor has reserved for its own use. Scan these ranges to choose
the lowest unused priority for the xive spapr backend.
Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
arch/powerpc/sysdev/xive/spapr.c | 62 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c
index 7fc40047c23d..220331986bd8 100644
--- a/arch/powerpc/sysdev/xive/spapr.c
+++ b/arch/powerpc/sysdev/xive/spapr.c
@@ -532,13 +532,70 @@ static const struct xive_ops xive_spapr_ops = {
.name = "spapr",
};
+/*
+ * get max priority from "/ibm,plat-res-int-priorities"
+ */
+static bool xive_get_max_prio(u8 *max_prio)
+{
+ struct device_node *rootdn;
+ const __be32 *reg;
+ u32 len;
+ int prio, found;
+
+ rootdn = of_find_node_by_path("/");
+ if (!rootdn) {
+ pr_err("not root node found !\n");
+ return false;
+ }
+
+ reg = of_get_property(rootdn, "ibm,plat-res-int-priorities", &len);
+ if (!reg) {
+ pr_err("Failed to read 'ibm,plat-res-int-priorities' property\n");
+ return false;
+ }
+
+ if (len % (2 * sizeof(u32)) != 0) {
+ pr_err("invalid 'ibm,plat-res-int-priorities' property\n");
+ return false;
+ }
+
+ /* HW supports priorities in the range [0-7] and 0xFF is a
+ * wildcard priority used to mask. We scan the ranges reserved
+ * by the hypervisor to find the lowest priority we can use.
+ */
+ found = 0xFF;
+ for (prio = 0; prio < 8; prio++) {
+ int reserved = 0;
+ int i;
+
+ for (i = 0; i < len / (2 * sizeof(u32)); i++) {
+ int base = be32_to_cpu(reg[2 * i]);
+ int range = be32_to_cpu(reg[2 * i + 1]);
+
+ if (prio >= base && prio < base + range)
+ reserved++;
+ }
+
+ if (!reserved)
+ found = prio;
+ }
+
+ if (found == 0xFF) {
+ pr_err("no valid priority found in 'ibm,plat-res-int-priorities'\n");
+ return false;
+ }
+
+ *max_prio = found;
+ return true;
+}
+
bool xive_spapr_init(void)
{
struct device_node *np;
struct resource r;
void __iomem *tima;
struct property *prop;
- u8 max_prio = 7;
+ u8 max_prio;
u32 val;
u32 len;
const __be32 *reg;
@@ -566,6 +623,9 @@ bool xive_spapr_init(void)
return false;
}
+ if (!xive_get_max_prio(&max_prio))
+ return false;
+
/* Feed the IRQ number allocator with the ranges given in the DT */
reg = of_get_property(np, "ibm,xive-lisn-ranges", &len);
if (!reg) {
--
2.7.5
More information about the Linuxppc-dev
mailing list