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. */
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to