The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/acpica/acpi_cpu_pstate.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
    3  * 
    4  * This code is derived from software contributed to The DragonFly Project
    5  * by Sepherosa Ziehau <sepherosa@gmail.com>
    6  * 
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in
   15  *    the documentation and/or other materials provided with the
   16  *    distribution.
   17  * 3. Neither the name of The DragonFly Project nor the names of its
   18  *    contributors may be used to endorse or promote products derived
   19  *    from this software without specific, prior written permission.
   20  * 
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include "opt_acpi.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/bus.h>
   39 #include <sys/kernel.h>
   40 #include <sys/malloc.h>
   41 #include <sys/queue.h>
   42 #include <sys/rman.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/msgport2.h>
   45 
   46 #include <net/netisr2.h>
   47 #include <net/netmsg2.h>
   48 #include <net/if_var.h>
   49 
   50 #include "acpi.h"
   51 #include "acpivar.h"
   52 #include "acpi_cpu.h"
   53 #include "acpi_cpu_pstate.h"
   54 
   55 #define ACPI_NPSTATE_MAX        16
   56 
   57 #define ACPI_PSS_PX_NENTRY      6
   58 
   59 #define ACPI_PSD_COORD_SWALL    0xfc
   60 #define ACPI_PSD_COORD_SWANY    0xfd
   61 #define ACPI_PSD_COORD_HWALL    0xfe
   62 #define ACPI_PSD_COORD_VALID(coord) \
   63         ((coord) == ACPI_PSD_COORD_SWALL || \
   64          (coord) == ACPI_PSD_COORD_SWANY || \
   65          (coord) == ACPI_PSD_COORD_HWALL)
   66 
   67 struct acpi_pst_softc;
   68 LIST_HEAD(acpi_pst_list, acpi_pst_softc);
   69 
   70 struct netmsg_acpi_pst {
   71         struct netmsg_base base;
   72         const struct acpi_pst_res *ctrl;
   73         const struct acpi_pst_res *status;
   74 };
   75 
   76 struct acpi_pst_domain {
   77         uint32_t                pd_dom;
   78         uint32_t                pd_coord;
   79         uint32_t                pd_nproc;
   80         LIST_ENTRY(acpi_pst_domain) pd_link;
   81 
   82         uint32_t                pd_flags;
   83 
   84         int                     pd_state;
   85         int                     pd_sstart;
   86         struct acpi_pst_list    pd_pstlist;
   87 
   88         struct sysctl_ctx_list  pd_sysctl_ctx;
   89         struct sysctl_oid       *pd_sysctl_tree;
   90 };
   91 LIST_HEAD(acpi_pst_domlist, acpi_pst_domain);
   92 
   93 #define ACPI_PSTDOM_FLAG_STUB   0x1     /* stub domain, no _PSD */
   94 #define ACPI_PSTDOM_FLAG_DEAD   0x2     /* domain can't be started */
   95 #define ACPI_PSTDOM_FLAG_INT    0x4     /* domain created from Integer _PSD */
   96 
   97 struct acpi_pst_softc {
   98         device_t                pst_dev;
   99         struct acpi_cpux_softc  *pst_parent;
  100         struct acpi_pst_domain  *pst_domain;
  101         struct acpi_pst_res     pst_creg;
  102         struct acpi_pst_res     pst_sreg;
  103 
  104         int                     pst_state;
  105         int                     pst_sstart;
  106         int                     pst_cpuid;
  107 
  108         ACPI_HANDLE             pst_handle;
  109 
  110         LIST_ENTRY(acpi_pst_softc) pst_link;
  111 };
  112 
  113 static int      acpi_pst_probe(device_t dev);
  114 static int      acpi_pst_attach(device_t dev);
  115 
  116 static void     acpi_pst_postattach(void *);
  117 static struct acpi_pst_domain *
  118                 acpi_pst_domain_create_int(device_t, uint32_t);
  119 static struct acpi_pst_domain *
  120                 acpi_pst_domain_create_pkg(device_t, ACPI_OBJECT *);
  121 static struct acpi_pst_domain *
  122                 acpi_pst_domain_find(uint32_t);
  123 static struct acpi_pst_domain *
  124                 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
  125 static int      acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int);
  126 static int      acpi_pst_global_set_pstate(int);
  127 
  128 static int      acpi_pst_check_csr(struct acpi_pst_softc *);
  129 static int      acpi_pst_check_pstates(struct acpi_pst_softc *);
  130 static int      acpi_pst_init(struct acpi_pst_softc *);
  131 static int      acpi_pst_set_pstate(struct acpi_pst_softc *,
  132                     const struct acpi_pstate *);
  133 static const struct acpi_pstate *
  134                 acpi_pst_get_pstate(struct acpi_pst_softc *);
  135 static int      acpi_pst_alloc_resource(device_t, ACPI_OBJECT *, int,
  136                     struct acpi_pst_res *);
  137 
  138 static void     acpi_pst_check_csr_handler(netmsg_t);
  139 static void     acpi_pst_check_pstates_handler(netmsg_t);
  140 static void     acpi_pst_init_handler(netmsg_t);
  141 static void     acpi_pst_set_pstate_handler(netmsg_t);
  142 static void     acpi_pst_get_pstate_handler(netmsg_t);
  143 
  144 static int      acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS);
  145 static int      acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS);
  146 static int      acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS);
  147 static int      acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS);
  148 
  149 static struct acpi_pst_domlist  acpi_pst_domains =
  150         LIST_HEAD_INITIALIZER(acpi_pst_domains);
  151 static int                      acpi_pst_domain_id;
  152 
  153 static int                      acpi_pst_global_state;
  154 
  155 static int                      acpi_npstates;
  156 static struct acpi_pstate       *acpi_pstates;
  157 
  158 static const struct acpi_pst_md *acpi_pst_md;
  159 
  160 static device_method_t acpi_pst_methods[] = {
  161         /* Device interface */
  162         DEVMETHOD(device_probe,                 acpi_pst_probe),
  163         DEVMETHOD(device_attach,                acpi_pst_attach),
  164         DEVMETHOD(device_detach,                bus_generic_detach),
  165         DEVMETHOD(device_shutdown,              bus_generic_shutdown),
  166         DEVMETHOD(device_suspend,               bus_generic_suspend),
  167         DEVMETHOD(device_resume,                bus_generic_resume),
  168 
  169         /* Bus interface */
  170         DEVMETHOD(bus_add_child,                bus_generic_add_child),
  171         DEVMETHOD(bus_print_child,              bus_generic_print_child),
  172         DEVMETHOD(bus_read_ivar,                bus_generic_read_ivar),
  173         DEVMETHOD(bus_write_ivar,               bus_generic_write_ivar),
  174         DEVMETHOD(bus_get_resource_list,        bus_generic_get_resource_list),
  175         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
  176         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
  177         DEVMETHOD(bus_alloc_resource,           bus_generic_alloc_resource),
  178         DEVMETHOD(bus_release_resource,         bus_generic_release_resource),
  179         DEVMETHOD(bus_driver_added,             bus_generic_driver_added),
  180         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
  181         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
  182         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
  183         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
  184 
  185         DEVMETHOD_END
  186 };
  187 
  188 static driver_t acpi_pst_driver = {
  189         "cpu_pst",
  190         acpi_pst_methods,
  191         sizeof(struct acpi_pst_softc)
  192 };
  193 
  194 static devclass_t acpi_pst_devclass;
  195 DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, NULL, NULL);
  196 MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1);
  197 
  198 static __inline int
  199 acpi_pst_freq2index(int freq)
  200 {
  201         int i;
  202 
  203         for (i = 0; i < acpi_npstates; ++i) {
  204                 if (acpi_pstates[i].st_freq == freq)
  205                         return i;
  206         }
  207         return -1;
  208 }
  209 
  210 static int
  211 acpi_pst_probe(device_t dev)
  212 {
  213         ACPI_BUFFER buf;
  214         ACPI_HANDLE handle;
  215         ACPI_STATUS status;
  216         ACPI_OBJECT *obj;
  217 
  218         if (acpi_disabled("cpu_pst") ||
  219             acpi_get_type(dev) != ACPI_TYPE_PROCESSOR)
  220                 return ENXIO;
  221 
  222         if (acpi_pst_md == NULL)
  223                 acpi_pst_md = acpi_pst_md_probe();
  224 
  225         handle = acpi_get_handle(dev);
  226 
  227         /*
  228          * Check _PCT package
  229          */
  230         buf.Pointer = NULL;
  231         buf.Length = ACPI_ALLOCATE_BUFFER;
  232         status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf);
  233         if (ACPI_FAILURE(status)) {
  234                 if (bootverbose) {
  235                         device_printf(dev, "Can't get _PCT package - %s\n",
  236                                       AcpiFormatException(status));
  237                 }
  238                 return ENXIO;
  239         }
  240 
  241         obj = (ACPI_OBJECT *)buf.Pointer;
  242         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
  243                 device_printf(dev, "Invalid _PCT package\n");
  244                 AcpiOsFree(obj);
  245                 return ENXIO;
  246         }
  247         AcpiOsFree(obj);
  248 
  249         /*
  250          * Check _PSS package
  251          */
  252         buf.Pointer = NULL;
  253         buf.Length = ACPI_ALLOCATE_BUFFER;
  254         status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf);
  255         if (ACPI_FAILURE(status)) {
  256                 device_printf(dev, "Can't get _PSS package - %s\n",
  257                               AcpiFormatException(status));
  258                 return ENXIO;
  259         }
  260 
  261         obj = (ACPI_OBJECT *)buf.Pointer;
  262         if (!ACPI_PKG_VALID(obj, 1)) {
  263                 device_printf(dev, "Invalid _PSS package\n");
  264                 AcpiOsFree(obj);
  265                 return ENXIO;
  266         }
  267         AcpiOsFree(obj);
  268 
  269         device_set_desc(dev, "ACPI CPU P-State");
  270         return 0;
  271 }
  272 
  273 static int
  274 acpi_pst_attach(device_t dev)
  275 {
  276         struct acpi_pst_softc *sc = device_get_softc(dev), *pst;
  277         struct acpi_pst_domain *dom = NULL;
  278         ACPI_BUFFER buf;
  279         ACPI_STATUS status;
  280         ACPI_OBJECT *obj;
  281         struct acpi_pstate *pstate, *p;
  282         int i, npstate, error;
  283 
  284         sc->pst_dev = dev;
  285         sc->pst_parent = device_get_softc(device_get_parent(dev));
  286         sc->pst_handle = acpi_get_handle(dev);
  287         sc->pst_cpuid = acpi_get_magic(dev);
  288 
  289         /*
  290          * If there is a _PSD, then we create procossor domain
  291          * accordingly.  If there is no _PSD, we just fake a
  292          * default processor domain0.
  293          */
  294         buf.Pointer = NULL;
  295         buf.Length = ACPI_ALLOCATE_BUFFER;
  296         status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf);
  297         if (!ACPI_FAILURE(status)) {
  298                 obj = (ACPI_OBJECT *)buf.Pointer;
  299 
  300                 if (acpi_pst_domain_id > 0) {
  301                         device_printf(dev, "Missing _PSD for certain CPUs\n");
  302                         AcpiOsFree(obj);
  303                         return ENXIO;
  304                 }
  305                 acpi_pst_domain_id = -1;
  306 
  307                 if (ACPI_PKG_VALID_EQ(obj, 1)) {
  308                         dom = acpi_pst_domain_create_pkg(dev,
  309                                 &obj->Package.Elements[0]);
  310                         if (dom == NULL) {
  311                                 AcpiOsFree(obj);
  312                                 return ENXIO;
  313                         }
  314                 } else {
  315                         if (obj->Type != ACPI_TYPE_INTEGER) {
  316                                 device_printf(dev,
  317                                     "Invalid _PSD package, Type 0x%x\n",
  318                                     obj->Type);
  319                                 AcpiOsFree(obj);
  320                                 return ENXIO;
  321                         } else {
  322                                 device_printf(dev, "Integer _PSD %ju\n",
  323                                     (uintmax_t)obj->Integer.Value);
  324                                 dom = acpi_pst_domain_create_int(dev,
  325                                     obj->Integer.Value);
  326                                 if (dom == NULL) {
  327                                         AcpiOsFree(obj);
  328                                         return ENXIO;
  329                                 }
  330                         }
  331                 }
  332 
  333                 /* Free _PSD */
  334                 AcpiOsFree(buf.Pointer);
  335         } else {
  336                 if (acpi_pst_domain_id < 0) {
  337                         device_printf(dev, "Missing _PSD for cpu%d\n",
  338                             sc->pst_cpuid);
  339                         return ENXIO;
  340                 }
  341 
  342                 /*
  343                  * Create a stub one processor domain for each processor
  344                  */
  345                 dom = acpi_pst_domain_alloc(acpi_pst_domain_id,
  346                         ACPI_PSD_COORD_SWANY, 1);
  347                 dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB;
  348 
  349                 ++acpi_pst_domain_id;
  350         }
  351 
  352         /* Make sure that adding us will not overflow our domain */
  353         i = 0;
  354         LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
  355                 ++i;
  356         if (i == dom->pd_nproc) {
  357                 device_printf(dev, "Domain%u already contains %d P-States, "
  358                               "invalid _PSD package\n",
  359                               dom->pd_dom, dom->pd_nproc);
  360 #if 0
  361                 /*
  362                  * Some stupid BIOSes will set wrong "# of processors",
  363                  * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
  364                  */
  365                 return ENXIO;
  366 #else
  367                 dom->pd_nproc++;
  368 #endif
  369         }
  370         KKASSERT(i < dom->pd_nproc);
  371 
  372         /*
  373          * Get control/status registers from _PCT
  374          */
  375         buf.Pointer = NULL;
  376         buf.Length = ACPI_ALLOCATE_BUFFER;
  377         status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf);
  378         if (ACPI_FAILURE(status)) {
  379                 device_printf(dev, "Can't get _PCT package - %s\n",
  380                               AcpiFormatException(status));
  381                 return ENXIO;
  382         }
  383 
  384         obj = (ACPI_OBJECT *)buf.Pointer;
  385         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
  386                 device_printf(dev, "Invalid _PCT package\n");
  387                 AcpiOsFree(obj);
  388                 return ENXIO;
  389         }
  390 
  391         /* Save and try allocating control register */
  392         error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg);
  393         if (error) {
  394                 AcpiOsFree(obj);
  395                 return error;
  396         }
  397         if (bootverbose) {
  398                 device_printf(dev, "control reg %d %jx\n",
  399                               sc->pst_creg.pr_gas.SpaceId,
  400                               (uintmax_t)sc->pst_creg.pr_gas.Address);
  401         }
  402 
  403         /* Save and try allocating status register */
  404         error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg);
  405         if (error) {
  406                 AcpiOsFree(obj);
  407                 return error;
  408         }
  409         if (bootverbose) {
  410                 device_printf(dev, "status reg %d %jx\n",
  411                               sc->pst_sreg.pr_gas.SpaceId,
  412                               (uintmax_t)sc->pst_sreg.pr_gas.Address);
  413         }
  414 
  415         /* Free _PCT */
  416         AcpiOsFree(obj);
  417 
  418         /*
  419          * Create P-State table according to _PSS
  420          */
  421         buf.Pointer = NULL;
  422         buf.Length = ACPI_ALLOCATE_BUFFER;
  423         status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf);
  424         if (ACPI_FAILURE(status)) {
  425                 device_printf(dev, "Can't get _PSS package - %s\n",
  426                               AcpiFormatException(status));
  427                 return ENXIO;
  428         }
  429 
  430         obj = (ACPI_OBJECT *)buf.Pointer;
  431         if (!ACPI_PKG_VALID(obj, 1)) {
  432                 device_printf(dev, "Invalid _PSS package\n");
  433                 AcpiOsFree(obj);
  434                 return ENXIO;
  435         }
  436 
  437         /* Don't create too many P-States */
  438         npstate = obj->Package.Count;
  439         if (npstate > ACPI_NPSTATE_MAX) {
  440                 device_printf(dev, "Too many P-States, %d->%d\n",
  441                               npstate, ACPI_NPSTATE_MAX);
  442                 npstate = ACPI_NPSTATE_MAX;
  443         }
  444 
  445         /*
  446          * If we have already created P-State table,
  447          * we must make sure that number of entries
  448          * is consistent.
  449          */
  450         if (acpi_pstates != NULL && acpi_npstates != npstate) {
  451                 device_printf(dev, "Inconsistent # of P-States "
  452                               "cross Processor objects\n");
  453                 AcpiOsFree(obj);
  454                 return ENXIO;
  455         }
  456 
  457         /*
  458          * Create a temporary P-State table
  459          */
  460         pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK);
  461         for (i = 0, p = pstate; i < npstate; ++i, ++p) {
  462                 ACPI_OBJECT *pkg;
  463                 uint32_t *ptr[ACPI_PSS_PX_NENTRY] = {
  464                         &p->st_freq, &p->st_power, &p->st_xsit_lat,
  465                         &p->st_bm_lat, &p->st_cval, &p->st_sval
  466                 };
  467                 int j;
  468 
  469                 pkg = &obj->Package.Elements[i];
  470                 if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) {
  471                         device_printf(dev, "Invalud _PSS P%d\n", i);
  472                         AcpiOsFree(obj);
  473                         kfree(pstate, M_TEMP);
  474                         return ENXIO;
  475                 }
  476                 for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) {
  477                         if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) {
  478                                 device_printf(dev, "Can't extract "
  479                                               "_PSS P%d %dth entry\n", i, j);
  480                                 AcpiOsFree(obj);
  481                                 kfree(pstate, M_TEMP);
  482                                 return ENXIO;
  483                         }
  484                 }
  485         }
  486 
  487         /* Free _PSS */
  488         AcpiOsFree(obj);
  489 
  490         if (acpi_pstates == NULL) {
  491                 /*
  492                  * If no P-State table is created yet,
  493                  * save the temporary one we just created.
  494                  */
  495                 acpi_pstates = pstate;
  496                 acpi_npstates = npstate;
  497                 pstate = NULL;
  498 
  499                 if (bootverbose) {
  500                         for (i = 0; i < acpi_npstates; ++i) {
  501                                 device_printf(dev,
  502                                 "freq %u, pwr %u, xlat %u, blat %u, "
  503                                 "cv %08x, sv %08x\n",
  504                                 acpi_pstates[i].st_freq,
  505                                 acpi_pstates[i].st_power,
  506                                 acpi_pstates[i].st_xsit_lat,
  507                                 acpi_pstates[i].st_bm_lat,
  508                                 acpi_pstates[i].st_cval,
  509                                 acpi_pstates[i].st_sval);
  510                         }
  511                 }
  512         } else {
  513                 /*
  514                  * Make sure that P-State tables are same
  515                  * for all processors.
  516                  */
  517                 if (memcmp(pstate, acpi_pstates,
  518                            sizeof(*pstate) * npstate) != 0) {
  519                         device_printf(dev, "Inconsistent _PSS "
  520                                       "cross Processor objects\n");
  521                         kfree(pstate, M_TEMP);
  522                         return ENXIO;
  523                 }
  524                 kfree(pstate, M_TEMP);
  525         }
  526 
  527         /* By default, we start from P-State table's first entry */
  528         sc->pst_sstart = 0;
  529 
  530         /*
  531          * Adjust the usable first entry of P-State table,
  532          * if there is _PPC object.
  533          */
  534         buf.Pointer = NULL;
  535         buf.Length = ACPI_ALLOCATE_BUFFER;
  536         status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf);
  537         if (!ACPI_FAILURE(status)) {
  538                 obj = (ACPI_OBJECT *)buf.Pointer;
  539                 if (obj->Type == ACPI_TYPE_INTEGER) {
  540                         if (obj->Integer.Value >= acpi_npstates) {
  541                                 device_printf(dev, "Invalid _PPC value\n");
  542                                 AcpiOsFree(obj);
  543                                 return ENXIO;
  544                         }
  545                         sc->pst_sstart = obj->Integer.Value;
  546                         if (bootverbose)
  547                                 device_printf(dev, "_PPC %d\n", sc->pst_sstart);
  548 
  549                         /* TODO: Install notifiy handler */
  550                 } else {
  551                         device_printf(dev, "Invalid _PPC object\n");
  552                         AcpiOsFree(obj);
  553                         return ENXIO;
  554                 }
  555 
  556                 /* Free _PPC */
  557                 AcpiOsFree(obj);
  558         }
  559 
  560         sc->pst_state = sc->pst_sstart;
  561 
  562         /* Link us with the domain */
  563         sc->pst_domain = dom;
  564         LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link);
  565 
  566         if (device_get_unit(dev) == 0)
  567                 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL);
  568 
  569         return 0;
  570 }
  571 
  572 static struct acpi_pst_domain *
  573 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj)
  574 {
  575         struct acpi_pst_domain *dom;
  576         uint32_t val, domain, coord, nproc;
  577 
  578         if (!ACPI_PKG_VALID_EQ(obj, 5)) {
  579                 device_printf(dev, "Invalid _PSD package\n");
  580                 return NULL;
  581         }
  582 
  583         /* NumberOfEntries */
  584         if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
  585                 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
  586                 return NULL;
  587         }
  588 
  589         /* Revision */
  590         if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
  591                 device_printf(dev, "Invalid _PSD Revision\n");
  592                 return NULL;
  593         }
  594 
  595         if (acpi_PkgInt32(obj, 2, &domain) != 0 ||
  596             acpi_PkgInt32(obj, 3, &coord) != 0 ||
  597             acpi_PkgInt32(obj, 4, &nproc) != 0) {
  598                 device_printf(dev, "Can't extract _PSD package\n");
  599                 return NULL;
  600         }
  601 
  602         if (!ACPI_PSD_COORD_VALID(coord)) {
  603                 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
  604                 return NULL;
  605         }
  606 
  607         if (nproc > MAXCPU) {
  608                 /*
  609                  * If NumProcessors is greater than MAXCPU
  610                  * and domain's coordination is SWALL, then
  611                  * we will never be able to start all CPUs
  612                  * within this domain, and power state
  613                  * transition will never be completed, so we
  614                  * just bail out here.
  615                  */
  616                 if (coord == ACPI_PSD_COORD_SWALL) {
  617                         device_printf(dev, "Unsupported _PSD NumProcessors "
  618                                       "(%d)\n", nproc);
  619                         return NULL;
  620                 }
  621         } else if (nproc == 0) {
  622                 device_printf(dev, "_PSD NumProcessors are zero\n");
  623                 return NULL;
  624         }
  625 
  626         dom = acpi_pst_domain_find(domain);
  627         if (dom != NULL) {
  628                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
  629                         device_printf(dev, "Mixed Integer _PSD and "
  630                             "Package _PSD\n");
  631                         return NULL;
  632                 }
  633                 if (dom->pd_coord != coord) {
  634                         device_printf(dev, "Inconsistent _PSD coord "
  635                             "information cross Processor objects\n");
  636                         return NULL;
  637                 }
  638                 if (dom->pd_nproc != nproc) {
  639                         device_printf(dev, "Inconsistent _PSD nproc "
  640                             "information cross Processor objects\n");
  641                         /*
  642                          * Some stupid BIOSes will set wrong "# of processors",
  643                          * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
  644                          */
  645                 }
  646                 return dom;
  647         }
  648 
  649         dom = acpi_pst_domain_alloc(domain, coord, nproc);
  650         if (bootverbose) {
  651                 device_printf(dev, "create pkg domain%u, coord %#x\n",
  652                     dom->pd_dom, dom->pd_coord);
  653         }
  654 
  655         return dom;
  656 }
  657 
  658 static struct acpi_pst_domain *
  659 acpi_pst_domain_create_int(device_t dev, uint32_t domain)
  660 {
  661         struct acpi_pst_domain *dom;
  662 
  663         dom = acpi_pst_domain_find(domain);
  664         if (dom != NULL) {
  665                 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
  666                         device_printf(dev, "Mixed Package _PSD and "
  667                             "Integer _PSD\n");
  668                         return NULL;
  669                 }
  670                 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
  671 
  672                 dom->pd_nproc++;
  673                 return dom;
  674         }
  675 
  676         dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
  677         dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
  678 
  679         if (bootverbose)
  680                 device_printf(dev, "create int domain%u\n", dom->pd_dom);
  681 
  682         return dom;
  683 }
  684 
  685 static struct acpi_pst_domain *
  686 acpi_pst_domain_find(uint32_t domain)
  687 {
  688         struct acpi_pst_domain *dom;
  689 
  690         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
  691                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB)
  692                         continue;
  693                 if (dom->pd_dom == domain)
  694                         return dom;
  695         }
  696         return NULL;
  697 }
  698 
  699 static struct acpi_pst_domain *
  700 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc)
  701 {
  702         struct acpi_pst_domain *dom;
  703 
  704         dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO);
  705         dom->pd_dom = domain;
  706         dom->pd_coord = coord;
  707         dom->pd_nproc = nproc;
  708         dom->pd_state = 0; /* XXX */
  709         dom->pd_sstart = 0; /* XXX */
  710         LIST_INIT(&dom->pd_pstlist);
  711 
  712         LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link);
  713 
  714         return dom;
  715 }
  716 
  717 static int
  718 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i)
  719 {
  720         const struct acpi_pstate *pstate;
  721         struct acpi_pst_softc *sc;
  722         int done, error;
  723 
  724         KKASSERT(i >= 0 && i < acpi_npstates);
  725         pstate = &acpi_pstates[i];
  726 
  727         done = 0;
  728         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
  729                 if (!done) {
  730                         error = acpi_pst_set_pstate(sc, pstate);
  731                         if (error) {
  732                                 device_printf(sc->pst_dev, "can't set "
  733                                               "freq %d\n", pstate->st_freq);
  734                                 /* XXX error cleanup? */
  735                         }
  736                         if (dom->pd_coord == ACPI_PSD_COORD_SWANY)
  737                                 done = 1;
  738                 }
  739                 sc->pst_state = i;
  740         }
  741         dom->pd_state = i;
  742 
  743         return 0;
  744 }
  745 
  746 static int
  747 acpi_pst_global_set_pstate(int i)
  748 {
  749         struct acpi_pst_domain *dom;
  750 
  751         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
  752                 /* Skip dead domain */
  753                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
  754                         continue;
  755                 acpi_pst_domain_set_pstate(dom, i);
  756         }
  757         acpi_pst_global_state = i;
  758 
  759         return 0;
  760 }
  761 
  762 static void
  763 acpi_pst_postattach(void *arg __unused)
  764 {
  765         struct acpi_pst_domain *dom;
  766         struct acpi_cpux_softc *cpux;
  767         device_t *devices;
  768         int i, ndevices, error, has_domain, sstate;
  769 
  770         devices = NULL;
  771         ndevices = 0;
  772         error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
  773         if (error)
  774                 return;
  775 
  776         if (ndevices == 0)
  777                 return;
  778 
  779         cpux = NULL;
  780         for (i = 0; i < ndevices; ++i) {
  781                 cpux = device_get_softc(device_get_parent(devices[i]));
  782                 if (cpux->glob_sysctl_tree != NULL)
  783                         break;
  784         }
  785         kfree(devices, M_TEMP);
  786         KKASSERT(cpux != NULL);
  787 
  788         if (acpi_pst_md == NULL)
  789                 kprintf("ACPI: no P-State CPU driver\n");
  790 
  791         sstate = 0x7fffffff;
  792         has_domain = 0;
  793         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
  794                 struct acpi_pst_softc *sc;
  795                 char buf[32];
  796 
  797                 /*
  798                  * Make sure that all processors belonging to this
  799                  * domain are located.
  800                  */
  801                 i = 0;
  802                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link)
  803                         ++i;
  804                 if (i != dom->pd_nproc) {
  805                         KKASSERT(i < dom->pd_nproc);
  806 
  807                         kprintf("ACPI: domain%u misses processors, "
  808                                 "should be %d, got %d\n", dom->pd_dom,
  809                                 dom->pd_nproc, i);
  810                         if (dom->pd_coord == ACPI_PSD_COORD_SWALL) {
  811                                 /*
  812                                  * If this domain's coordination is
  813                                  * SWALL and we don't see all of the
  814                                  * member CPUs of this domain, then
  815                                  * the P-State transition will never
  816                                  * be completed, so just leave this
  817                                  * domain out.
  818                                  */
  819                                 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
  820                                 continue;
  821                         }
  822                         dom->pd_nproc = i;
  823                 }
  824 
  825                 /*
  826                  * Validate P-State configurations for this domain
  827                  */
  828                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
  829                         error = acpi_pst_check_csr(sc);
  830                         if (error)
  831                                 break;
  832 
  833                         error = acpi_pst_check_pstates(sc);
  834                         if (error)
  835                                 break;
  836                 }
  837                 if (sc != NULL) {
  838                         kprintf("ACPI: domain%u P-State configuration "
  839                                 "check failed\n", dom->pd_dom);
  840                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
  841                         continue;
  842                 }
  843 
  844                 /*
  845                  * Do necssary P-State initialization
  846                  */
  847                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
  848                         error = acpi_pst_init(sc);
  849                         if (error)
  850                                 break;
  851                 }
  852                 if (sc != NULL) {
  853                         kprintf("ACPI: domain%u P-State initialization "
  854                                 "check failed\n", dom->pd_dom);
  855                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
  856                         continue;
  857                 }
  858 
  859                 has_domain = 1;
  860 
  861                 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom);
  862 
  863                 sysctl_ctx_init(&dom->pd_sysctl_ctx);
  864                 dom->pd_sysctl_tree =
  865                 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx,
  866                         SYSCTL_CHILDREN(cpux->glob_sysctl_tree),
  867                         OID_AUTO, buf, CTLFLAG_RD, 0,
  868                         "P-State domain");
  869                 if (dom->pd_sysctl_tree == NULL) {
  870                         kprintf("ACPI: Can't create sysctl tree for domain%u",
  871                                 dom->pd_dom);
  872                         continue;
  873                 }
  874 
  875                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
  876                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
  877                                 OID_AUTO, "available",
  878                                 CTLTYPE_STRING | CTLFLAG_RD,
  879                                 dom, 0, acpi_pst_sysctl_freqs, "A",
  880                                 "available frequencies");
  881 
  882                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
  883                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
  884                                 OID_AUTO, "members",
  885                                 CTLTYPE_STRING | CTLFLAG_RD,
  886                                 dom, 0, acpi_pst_sysctl_members, "A",
  887                                 "member cpus");
  888 
  889                 if (acpi_pst_md != NULL &&
  890                     acpi_pst_md->pmd_set_pstate != NULL) {
  891                         SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
  892                                         SYSCTL_CHILDREN(dom->pd_sysctl_tree),
  893                                         OID_AUTO, "select",
  894                                         CTLTYPE_UINT | CTLFLAG_RW,
  895                                         dom, 0, acpi_pst_sysctl_select,
  896                                         "IU", "select freq");
  897                 }
  898 
  899                 if (dom->pd_state < sstate)
  900                         sstate = dom->pd_state;
  901         }
  902 
  903         if (has_domain && acpi_pst_md != NULL &&
  904             acpi_pst_md->pmd_set_pstate != NULL) {
  905                 SYSCTL_ADD_PROC(&cpux->glob_sysctl_ctx,
  906                                 SYSCTL_CHILDREN(cpux->glob_sysctl_tree),
  907                                 OID_AUTO, "px_global",
  908                                 CTLTYPE_UINT | CTLFLAG_RW,
  909                                 NULL, 0, acpi_pst_sysctl_global,
  910                                 "IU", "select freq for all domains");
  911 
  912                 acpi_pst_global_set_pstate(sstate);
  913         }
  914 }
  915 
  916 static int
  917 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
  918 {
  919         struct acpi_pst_domain *dom = arg1;
  920         int i, error;
  921 
  922         error = 0;
  923         for (i = 0; i < acpi_npstates; ++i) {
  924                 if (error == 0 && i)
  925                         error = SYSCTL_OUT(req, " ", 1);
  926                 if (error == 0) {
  927                         const char *pat;
  928                         char buf[32];
  929 
  930                         if (i < dom->pd_sstart)
  931                                 pat = "(%u)";
  932                         else
  933                                 pat = "%u";
  934 
  935                         ksnprintf(buf, sizeof(buf), pat,
  936                                   acpi_pstates[i].st_freq);
  937                         error = SYSCTL_OUT(req, buf, strlen(buf));
  938                 }
  939         }
  940         return error;
  941 }
  942 
  943 static int
  944 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
  945 {
  946         struct acpi_pst_domain *dom = arg1;
  947         struct acpi_pst_softc *sc;
  948         int loop, error;
  949 
  950         loop = error = 0;
  951         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
  952                 char buf[32];
  953 
  954                 if (error == 0 && loop)
  955                         error = SYSCTL_OUT(req, " ", 1);
  956                 if (error == 0) {
  957                         ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid);
  958                         error = SYSCTL_OUT(req, buf, strlen(buf));
  959                 }
  960 
  961                 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) {
  962                         const struct acpi_pstate *pstate;
  963                         const char *str;
  964 
  965                         pstate = acpi_pst_get_pstate(sc);
  966                         if (pstate == NULL) {
  967                                 str = "(*)";
  968                         } else {
  969                                 ksnprintf(buf, sizeof(buf), "(%d)",
  970                                           pstate->st_freq);
  971                                 str = buf;
  972                         }
  973                         error = SYSCTL_OUT(req, str, strlen(str));
  974                 }
  975                 ++loop;
  976         }
  977         return error;
  978 }
  979 
  980 static int
  981 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
  982 {
  983         struct acpi_pst_domain *dom = arg1;
  984         int error, i, freq;
  985 
  986         KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates);
  987 
  988         freq = acpi_pstates[dom->pd_state].st_freq;
  989 
  990         error = sysctl_handle_int(oidp, &freq, 0, req);
  991         if (error || req->newptr == NULL)
  992                 return error;
  993 
  994         i = acpi_pst_freq2index(freq);
  995         if (i < 0)
  996                 return EINVAL;
  997 
  998         acpi_pst_domain_set_pstate(dom, i);
  999         return 0;
 1000 }
 1001 
 1002 static int
 1003 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
 1004 {
 1005         int error, i, freq;
 1006 
 1007         KKASSERT(acpi_pst_global_state >= 0 &&
 1008                  acpi_pst_global_state < acpi_npstates);
 1009 
 1010         freq = acpi_pstates[acpi_pst_global_state].st_freq;
 1011 
 1012         error = sysctl_handle_int(oidp, &freq, 0, req);
 1013         if (error || req->newptr == NULL)
 1014                 return error;
 1015 
 1016         i = acpi_pst_freq2index(freq);
 1017         if (i < 0)
 1018                 return EINVAL;
 1019 
 1020         acpi_pst_global_set_pstate(i);
 1021 
 1022         return 0;
 1023 }
 1024 
 1025 static void
 1026 acpi_pst_check_csr_handler(netmsg_t msg)
 1027 {
 1028         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
 1029         int error;
 1030 
 1031         error = acpi_pst_md->pmd_check_csr(rmsg->ctrl, rmsg->status);
 1032         lwkt_replymsg(&rmsg->base.lmsg, error);
 1033 }
 1034 
 1035 static int
 1036 acpi_pst_check_csr(struct acpi_pst_softc *sc)
 1037 {
 1038         struct netmsg_acpi_pst msg;
 1039 
 1040         if (acpi_pst_md == NULL)
 1041                 return 0;
 1042 
 1043         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
 1044                     MSGF_PRIORITY, acpi_pst_check_csr_handler);
 1045         msg.ctrl = &sc->pst_creg;
 1046         msg.status = &sc->pst_sreg;
 1047 
 1048         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
 1049 }
 1050 
 1051 static void
 1052 acpi_pst_check_pstates_handler(netmsg_t msg)
 1053 {
 1054         int error;
 1055 
 1056         error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
 1057         lwkt_replymsg(&msg->lmsg, error);
 1058 }
 1059 
 1060 static int
 1061 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
 1062 {
 1063         struct netmsg_base msg;
 1064 
 1065         if (acpi_pst_md == NULL)
 1066                 return 0;
 1067 
 1068         netmsg_init(&msg, NULL, &curthread->td_msgport,
 1069                     MSGF_PRIORITY, acpi_pst_check_pstates_handler);
 1070 
 1071         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.lmsg, 0);
 1072 }
 1073 
 1074 static void
 1075 acpi_pst_init_handler(netmsg_t msg)
 1076 {
 1077         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
 1078         int error;
 1079 
 1080         error = acpi_pst_md->pmd_init(rmsg->ctrl, rmsg->status);
 1081         lwkt_replymsg(&rmsg->base.lmsg, error);
 1082 }
 1083 
 1084 static int
 1085 acpi_pst_init(struct acpi_pst_softc *sc)
 1086 {
 1087         struct netmsg_acpi_pst msg;
 1088 
 1089         if (acpi_pst_md == NULL)
 1090                 return 0;
 1091 
 1092         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
 1093                     MSGF_PRIORITY, acpi_pst_init_handler);
 1094         msg.ctrl = &sc->pst_creg;
 1095         msg.status = &sc->pst_sreg;
 1096 
 1097         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
 1098 }
 1099 
 1100 static void
 1101 acpi_pst_set_pstate_handler(netmsg_t msg)
 1102 {
 1103         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
 1104         int error;
 1105 
 1106         error = acpi_pst_md->pmd_set_pstate(rmsg->ctrl, rmsg->status,
 1107                                             rmsg->base.lmsg.u.ms_resultp);
 1108         lwkt_replymsg(&rmsg->base.lmsg, error);
 1109 }
 1110 
 1111 static int
 1112 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
 1113 {
 1114         struct netmsg_acpi_pst msg;
 1115 
 1116         KKASSERT(acpi_pst_md != NULL);
 1117 
 1118         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
 1119                     MSGF_PRIORITY, acpi_pst_set_pstate_handler);
 1120         msg.base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
 1121         msg.ctrl = &sc->pst_creg;
 1122         msg.status = &sc->pst_sreg;
 1123 
 1124         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
 1125 }
 1126 
 1127 static void
 1128 acpi_pst_get_pstate_handler(netmsg_t msg)
 1129 {
 1130         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
 1131         const struct acpi_pstate *pstate;
 1132 
 1133         pstate = acpi_pst_md->pmd_get_pstate(rmsg->status, acpi_pstates,
 1134                                              acpi_npstates);
 1135         rmsg->base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
 1136         lwkt_replymsg(&rmsg->base.lmsg, 0);
 1137 }
 1138 
 1139 static const struct acpi_pstate *
 1140 acpi_pst_get_pstate(struct acpi_pst_softc *sc)
 1141 {
 1142         struct netmsg_acpi_pst msg;
 1143 
 1144         if (acpi_pst_md == NULL)
 1145                 return 0;
 1146 
 1147         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
 1148                     MSGF_PRIORITY, acpi_pst_get_pstate_handler);
 1149         msg.status = &sc->pst_sreg;
 1150 
 1151         lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
 1152         return msg.base.lmsg.u.ms_resultp;
 1153 }
 1154 
 1155 static int
 1156 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx,
 1157                         struct acpi_pst_res *res)
 1158 {
 1159         struct acpi_pst_softc *sc = device_get_softc(dev);
 1160         int error, type;
 1161 
 1162         /* Save GAS */
 1163         error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
 1164         if (error)
 1165                 return error;
 1166 
 1167         /* Allocate resource, if possible */
 1168         res->pr_rid = sc->pst_parent->cpux_next_rid;
 1169         acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0);
 1170         if (res->pr_res != NULL) {
 1171                 sc->pst_parent->cpux_next_rid++;
 1172                 res->pr_bt = rman_get_bustag(res->pr_res);
 1173                 res->pr_bh = rman_get_bushandle(res->pr_res);
 1174         } else {
 1175                 res->pr_rid = 0;
 1176         }
 1177         return 0;
 1178 }

Cache object: b890c75858ebccc986c812a17ecf405a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.