Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jun 2018 14:54:17 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r334999 - head/sys/dev/psci
Message-ID:  <201806121454.w5CEsHbJ043013@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Tue Jun 12 14:54:17 2018
New Revision: 334999
URL: https://svnweb.freebsd.org/changeset/base/334999

Log:
  Rework PSCI so it only searches for the call function once.
  
  This is in preperation for supporting newer smccc functions that also use
  the same call method.
  
  Reviewed by:	manu
  Differential Revision:	https://reviews.freebsd.org/D15745

Modified:
  head/sys/dev/psci/psci.c

Modified: head/sys/dev/psci/psci.c
==============================================================================
--- head/sys/dev/psci/psci.c	Tue Jun 12 13:32:42 2018	(r334998)
+++ head/sys/dev/psci/psci.c	Tue Jun 12 14:54:17 2018	(r334999)
@@ -74,7 +74,6 @@ __FBSDID("$FreeBSD$");
 struct psci_softc {
 	device_t        dev;
 
-	psci_callfn_t	psci_call;
 	uint32_t	psci_fnids[PSCI_FN_MAX];
 };
 
@@ -107,6 +106,41 @@ static struct ofw_compat_data compat_data[] = {
 static int psci_attach(device_t, psci_initfn_t);
 static void psci_shutdown(void *, int);
 
+static int psci_find_callfn(psci_callfn_t *);
+static int psci_def_callfn(register_t, register_t, register_t, register_t);
+
+static psci_callfn_t psci_callfn = psci_def_callfn;
+
+static inline int
+psci_call(register_t a, register_t b, register_t c, register_t d)
+{
+
+	return (psci_callfn(a, b, c, d));
+}
+
+static void
+psci_init(void *dummy)
+{
+	psci_callfn_t new_callfn;
+
+	if (psci_find_callfn(&new_callfn) != PSCI_RETVAL_SUCCESS) {
+		printf("No PSCI/SMCCC call function found");
+		return;
+	}
+
+	psci_callfn = new_callfn;
+}
+/* This needs to be before cpu_mp at SI_SUB_CPU, SI_ORDER_THIRD */
+SYSINIT(psci_start, SI_SUB_CPU, SI_ORDER_FIRST, psci_init, NULL);
+
+static int
+psci_def_callfn(register_t a __unused, register_t b __unused,
+    register_t c __unused, register_t d __unused)
+{
+
+	panic("No PSCI/SMCCC call function set");
+}
+
 #ifdef FDT
 static int psci_fdt_probe(device_t dev);
 static int psci_fdt_attach(device_t dev);
@@ -169,17 +203,12 @@ psci_fdt_probe(device_t dev)
 static int
 psci_fdt_attach(device_t dev)
 {
-	struct psci_softc *sc = device_get_softc(dev);
 	const struct ofw_compat_data *ocd;
 	psci_initfn_t psci_init;
-	phandle_t node;
 
 	ocd = ofw_bus_search_compatible(dev, compat_data);
 	psci_init = (psci_initfn_t)ocd->ocd_data;
 
-	node = ofw_bus_get_node(dev);
-	sc->psci_call = psci_fdt_get_callfn(node);
-
 	return (psci_attach(dev, psci_init));
 }
 #endif
@@ -280,15 +309,7 @@ psci_acpi_probe(device_t dev)
 static int
 psci_acpi_attach(device_t dev)
 {
-	struct psci_softc *sc = device_get_softc(dev);
-	uintptr_t flags;
 
-	flags = (uintptr_t)acpi_get_private(dev);
-	if ((flags & ACPI_FADT_PSCI_USE_HVC) != 0)
-		sc->psci_call = psci_hvc_despatch;
-	else
-		sc->psci_call = psci_smc_despatch;
-
 	return (psci_attach(dev, psci_v0_2_init));
 }
 #endif
@@ -301,9 +322,6 @@ psci_attach(device_t dev, psci_initfn_t psci_init)
 	if (psci_softc != NULL)
 		return (ENXIO);
 
-	if (sc->psci_call == NULL)
-		return (ENXIO);
-
 	KASSERT(psci_init != NULL, ("PSCI init function cannot be NULL"));
 	if (psci_init(dev))
 		return (ENXIO);
@@ -321,7 +339,7 @@ _psci_get_version(struct psci_softc *sc)
 	/* PSCI version wasn't supported in v0.1. */
 	fnid = sc->psci_fnids[PSCI_FN_VERSION];
 	if (fnid)
-		return (sc->psci_call(fnid, 0, 0, 0));
+		return (psci_call(fnid, 0, 0, 0));
 
 	return (PSCI_RETVAL_NOT_SUPPORTED);
 }
@@ -368,40 +386,44 @@ psci_acpi_callfn(psci_callfn_t *callfn)
 }
 #endif
 
-int
-psci_cpu_on(unsigned long cpu, unsigned long entry, unsigned long context_id)
+static int
+psci_find_callfn(psci_callfn_t *callfn)
 {
-	psci_callfn_t callfn;
-	uint32_t fnid;
 	int error;
 
-	if (psci_softc == NULL) {
-		fnid = PSCI_FNID_CPU_ON;
-		callfn = NULL;
+	*callfn = NULL;
 #ifdef FDT
-		if (USE_FDT) {
-			error = psci_fdt_callfn(&callfn);
-			if (error != 0)
-				return (error);
-		}
+	if (USE_FDT) {
+		error = psci_fdt_callfn(callfn);
+		if (error != 0)
+			return (error);
+	}
 #endif
 #ifdef DEV_ACPI
-		if (callfn == NULL && USE_ACPI) {
-			error = psci_acpi_callfn(&callfn);
-			if (error != 0)
-				return (error);
-		}
+	if (*callfn == NULL && USE_ACPI) {
+		error = psci_acpi_callfn(callfn);
+		if (error != 0)
+			return (error);
+	}
 #endif
 
-		if (callfn == NULL)
-			return (PSCI_MISSING);
-	} else {
-		callfn = psci_softc->psci_call;
+	if (*callfn == NULL)
+		return (PSCI_MISSING);
+
+	return (PSCI_RETVAL_SUCCESS);
+}
+
+int
+psci_cpu_on(unsigned long cpu, unsigned long entry, unsigned long context_id)
+{
+	uint32_t fnid;
+
+	fnid = PSCI_FNID_CPU_ON;
+	if (psci_softc != NULL)
 		fnid = psci_softc->psci_fnids[PSCI_FN_CPU_ON];
-	}
 
 	/* PSCI v0.1 and v0.2 both support cpu_on. */
-	return (callfn(fnid, cpu, entry, context_id));
+	return (psci_call(fnid, cpu, entry, context_id));
 }
 
 static void
@@ -419,7 +441,7 @@ psci_shutdown(void *xsc, int howto)
 		fn = psci_softc->psci_fnids[PSCI_FN_SYSTEM_RESET];
 
 	if (fn)
-		psci_softc->psci_call(fn, 0, 0, 0);
+		psci_call(fn, 0, 0, 0);
 
 	/* System reset and off do not return. */
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806121454.w5CEsHbJ043013>