svn commit: r334999 - head/sys/dev/psci
Andrew Turner
andrew at FreeBSD.org
Tue Jun 12 14:54:18 UTC 2018
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. */
}
More information about the svn-src-head
mailing list