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/compat/linuxkpi/common/src/linux_acpi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2018 Johannes Lundberg <johalun@FreeBSD.org>
    5  * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions are
    9  * met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in
   14  *    the documentation and/or other materials provided with the
   15  *    distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD$
   30  */
   31 
   32 #include "opt_acpi.h"
   33 
   34 #include <sys/types.h>
   35 #include <sys/bus.h>
   36 #include <sys/eventhandler.h>
   37 #include <sys/kernel.h>
   38 
   39 #include <contrib/dev/acpica/include/acpi.h>
   40 #include <dev/acpica/acpivar.h>
   41 
   42 #include <linux/notifier.h>
   43 #include <linux/suspend.h>
   44 
   45 #include <acpi/acpi_bus.h>
   46 #include <acpi/video.h>
   47 
   48 #define ACPI_AC_CLASS   "ac_adapter"
   49 
   50 ACPI_MODULE_NAME("linux_acpi")
   51 
   52 enum {
   53         LINUX_ACPI_ACAD,
   54         LINUX_ACPI_VIDEO,
   55         LINUX_ACPI_TAGS                 /* must be last */
   56 };
   57 _Static_assert(LINUX_ACPI_TAGS <= LINUX_NOTIFY_TAGS,
   58     "Not enough space for tags in notifier_block structure");
   59 
   60 #ifdef DEV_ACPI
   61 
   62 suspend_state_t pm_suspend_target_state = PM_SUSPEND_ON;
   63 
   64 static uint32_t linux_acpi_target_sleep_state = ACPI_STATE_S0;
   65 
   66 static eventhandler_tag resume_tag;
   67 static eventhandler_tag suspend_tag;
   68 
   69 ACPI_HANDLE
   70 bsd_acpi_get_handle(device_t bsddev)
   71 {
   72         return (acpi_get_handle(bsddev));
   73 }
   74 
   75 bool
   76 acpi_check_dsm(ACPI_HANDLE handle, const char *uuid, int rev, uint64_t funcs)
   77 {
   78 
   79         if (funcs == 0)
   80                 return (false);
   81 
   82         /*
   83          * From ACPI 6.3 spec 9.1.1:
   84          * Bit 0 indicates whether there is support for any functions other
   85          * than function 0 for the specified UUID and Revision ID. If set to
   86          * zero, no functions are supported (other than function zero) for the
   87          * specified UUID and Revision ID.
   88          */
   89         funcs |= 1 << 0;
   90 
   91         return ((acpi_DSMQuery(handle, uuid, rev) & funcs) == funcs);
   92 }
   93 
   94 ACPI_OBJECT *
   95 acpi_evaluate_dsm_typed(ACPI_HANDLE handle, const char *uuid, int rev,
   96     int func, ACPI_OBJECT *argv4, ACPI_OBJECT_TYPE type)
   97 {
   98         ACPI_BUFFER buf;
   99 
  100         return (ACPI_SUCCESS(acpi_EvaluateDSMTyped(handle, uuid, rev, func,
  101             argv4, &buf, type)) ? (ACPI_OBJECT *)buf.Pointer : NULL);
  102 }
  103 
  104 static void
  105 linux_handle_power_suspend_event(void *arg __unused)
  106 {
  107         /*
  108          * Only support S3 for now.
  109          * acpi_sleep_event isn't always called so we use power_suspend_early
  110          * instead which means we don't know what state we're switching to.
  111          * TODO: Make acpi_sleep_event consistent
  112          */
  113         linux_acpi_target_sleep_state = ACPI_STATE_S3;
  114 }
  115 
  116 static void
  117 linux_handle_power_resume_event(void *arg __unused)
  118 {
  119         linux_acpi_target_sleep_state = ACPI_STATE_S0;
  120 }
  121 
  122 static void
  123 linux_handle_acpi_acad_event(void *arg, int data)
  124 {
  125         struct notifier_block *nb = arg;
  126         /*
  127          * Event type information is lost ATM in FreeBSD ACPI event handler.
  128          * Fortunately, drm-kmod do not distinct AC event types too, so we can
  129          * use any type e.g. ACPI_NOTIFY_BUS_CHECK that suits notifier handler.
  130          */
  131         struct acpi_bus_event abe = {
  132             .device_class = ACPI_AC_CLASS,
  133             .type = ACPI_NOTIFY_BUS_CHECK,
  134             .data = data,
  135         };
  136 
  137         nb->notifier_call(nb, 0, &abe);
  138 }
  139 
  140 static void
  141 linux_handle_acpi_video_event(void *arg, int type)
  142 {
  143         struct notifier_block *nb = arg;
  144         struct acpi_bus_event abe = {
  145             .device_class = ACPI_VIDEO_CLASS,
  146             .type = type,
  147             .data = 0,
  148         };
  149 
  150         nb->notifier_call(nb, 0, &abe);
  151 }
  152 
  153 int
  154 register_acpi_notifier(struct notifier_block *nb)
  155 {
  156         nb->tags[LINUX_ACPI_ACAD] = EVENTHANDLER_REGISTER(acpi_acad_event,
  157             linux_handle_acpi_acad_event, nb, EVENTHANDLER_PRI_FIRST);
  158         nb->tags[LINUX_ACPI_VIDEO] = EVENTHANDLER_REGISTER(acpi_video_event,
  159             linux_handle_acpi_video_event, nb, EVENTHANDLER_PRI_FIRST);
  160 
  161         return (0);
  162 }
  163 
  164 int
  165 unregister_acpi_notifier(struct notifier_block *nb)
  166 {
  167         EVENTHANDLER_DEREGISTER(acpi_acad_event, nb->tags[LINUX_ACPI_ACAD]);
  168         EVENTHANDLER_DEREGISTER(acpi_video_event, nb->tags[LINUX_ACPI_VIDEO]);
  169 
  170         return (0);
  171 }
  172 
  173 uint32_t
  174 acpi_target_system_state(void)
  175 {
  176         return (linux_acpi_target_sleep_state);
  177 }
  178 
  179 static void
  180 linux_register_acpi_event_handlers(void *arg __unused)
  181 {
  182         /*
  183          * XXX johalun: acpi_{sleep,wakeup}_event can't be trusted, use
  184          * power_{suspend_early,resume} 'acpiconf -s 3' or 'zzz' will not
  185          * generate acpi_sleep_event... Lid open or wake on button generates
  186          * acpi_wakeup_event on one of my Dell laptops but not the other
  187          * (but it does power on)... is this a general thing?
  188          */
  189         resume_tag = EVENTHANDLER_REGISTER(power_resume,
  190             linux_handle_power_resume_event, NULL, EVENTHANDLER_PRI_FIRST);
  191         suspend_tag = EVENTHANDLER_REGISTER(power_suspend_early,
  192             linux_handle_power_suspend_event, NULL, EVENTHANDLER_PRI_FIRST);
  193 }
  194 
  195 static void
  196 linux_deregister_acpi_event_handlers(void *arg __unused)
  197 {
  198         EVENTHANDLER_DEREGISTER(power_resume, resume_tag);
  199         EVENTHANDLER_DEREGISTER(power_suspend_early, suspend_tag);
  200 }
  201 
  202 SYSINIT(linux_acpi_events, SI_SUB_DRIVERS, SI_ORDER_ANY,
  203     linux_register_acpi_event_handlers, NULL);
  204 SYSUNINIT(linux_acpi_events, SI_SUB_DRIVERS, SI_ORDER_ANY,
  205     linux_deregister_acpi_event_handlers, NULL);
  206 
  207 #else   /* !DEV_ACPI */
  208 
  209 ACPI_HANDLE
  210 bsd_acpi_get_handle(device_t bsddev)
  211 {
  212         return (NULL);
  213 }
  214 
  215 bool
  216 acpi_check_dsm(ACPI_HANDLE handle, const char *uuid, int rev, uint64_t funcs)
  217 {
  218         return (false);
  219 }
  220 
  221 ACPI_OBJECT *
  222 acpi_evaluate_dsm_typed(ACPI_HANDLE handle, const char *uuid, int rev,
  223      int func, ACPI_OBJECT *argv4, ACPI_OBJECT_TYPE type)
  224 {
  225         return (NULL);
  226 }
  227 
  228 int
  229 register_acpi_notifier(struct notifier_block *nb)
  230 {
  231         return (0);
  232 }
  233 
  234 int
  235 unregister_acpi_notifier(struct notifier_block *nb)
  236 {
  237         return (0);
  238 }
  239 
  240 uint32_t
  241 acpi_target_system_state(void)
  242 {
  243         return (ACPI_STATE_S0);
  244 }
  245 
  246 #endif  /* !DEV_ACPI */

Cache object: 3d3fdd3a5138bb1fcb359510f08bc679


[ 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.