1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1999-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #define  __NO_VERSION__
25 
26 #include "os-interface.h"
27 #include "nv-linux.h"
28 #include "nv-reg.h"
29 
30 #include <linux/acpi.h>
31 
32 #if defined(NV_LINUX_ACPI_EVENTS_SUPPORTED)
33 static NV_STATUS   nv_acpi_extract_integer (const union acpi_object *, void *, NvU32, NvU32 *);
34 static NV_STATUS   nv_acpi_extract_buffer  (const union acpi_object *, void *, NvU32, NvU32 *);
35 static NV_STATUS   nv_acpi_extract_package (const union acpi_object *, void *, NvU32, NvU32 *);
36 static NV_STATUS   nv_acpi_extract_object  (const union acpi_object *, void *, NvU32, NvU32 *);
37 
38 static void        nv_acpi_powersource_hotplug_event(acpi_handle, u32, void *);
39 static void        nv_acpi_nvpcf_event     (acpi_handle, u32, void *);
40 static acpi_status nv_acpi_find_methods    (acpi_handle, u32, void *, void **);
41 static NV_STATUS   nv_acpi_nvif_method     (NvU32, NvU32, void *, NvU16, NvU32 *, void *, NvU16 *);
42 
43 static NV_STATUS   nv_acpi_wmmx_method     (NvU32, NvU8 *, NvU16 *);
44 
45 static acpi_handle nvif_handle = NULL;
46 static acpi_handle wmmx_handle = NULL;
47 
48 // Used for AC Power Source Hotplug Handling
49 static acpi_handle psr_handle = NULL;
50 static acpi_handle psr_device_handle = NULL;
51 static nv_acpi_t  *psr_nv_acpi_object = NULL;
52 
53 static NvBool battery_present = NV_FALSE;
54 
55 #define BIX_BATTERY_TECHNOLOGY_OFFSET 0x4
56 #define BIF_BATTERY_TECHNOLOGY_OFFSET 0x3
57 #define BATTERY_RECHARGABLE           0x1
58 
59 /* Moved into acpi/video.h in Linux 4.10 */
60 #ifndef ACPI_VIDEO_NOTIFY_PROBE
61 #define ACPI_VIDEO_NOTIFY_PROBE    0x81
62 #endif
63 
64 /* Added to acpi/video.h in Linux 3.1 */
65 #ifndef ACPI_VIDEO_CLASS
66 #define ACPI_VIDEO_CLASS    "video"
67 #endif
68 
69 // Used for NVPCF event handling
70 static acpi_handle nvpcf_handle = NULL;
71 static acpi_handle nvpcf_device_handle = NULL;
72 static nv_acpi_t  *nvpcf_nv_acpi_object = NULL;
73 
74 #define ACPI_NVPCF_EVENT_CHANGE    0xC0
75 
76 static int nv_acpi_get_device_handle(nv_state_t *nv, acpi_handle *dev_handle)
77 {
78     nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv);
79 
80 #if defined(DEVICE_ACPI_HANDLE)
81     *dev_handle = DEVICE_ACPI_HANDLE(nvl->dev);
82     return NV_TRUE;
83 #elif defined (ACPI_HANDLE)
84     *dev_handle = ACPI_HANDLE(nvl->dev);
85     return NV_TRUE;
86 #else
87     return NV_FALSE;
88 #endif
89 }
90 
91 /*
92  * This callback will be invoked by the acpi_notifier_call_chain()
93  */
94 static int nv_acpi_notifier_call_chain_handler(
95     struct notifier_block *nb,
96     unsigned long val,
97     void *data
98 )
99 {
100     struct acpi_bus_event *info = data;
101     nv_stack_t *sp = NULL;
102     nv_linux_state_t *nvl = container_of(nb, nv_linux_state_t, acpi_nb);
103     nv_state_t *nv = NV_STATE_PTR(nvl);
104 
105     /*
106      * The ACPI_VIDEO_NOTIFY_PROBE will be sent for display hot-plug/unplug.
107      * This event will be received first by the acpi-video driver
108      * and then it will be notified through acpi_notifier_call_chain().
109      */
110     if (!strcmp(info->device_class, ACPI_VIDEO_CLASS) &&
111         (info->type == ACPI_VIDEO_NOTIFY_PROBE))
112     {
113         /*
114          * Intentionally return NOTIFY_BAD to inform acpi-video to stop
115          * generating keypresses for this event. The default behavior in the
116          * acpi-video driver for an ACPI_VIDEO_NOTIFY_PROBE, is to send a
117          * KEY_SWITCHVIDEOMODE evdev event, which causes the desktop settings
118          * daemons like gnome-setting-daemon to switch mode and this impacts
119          * the notebooks having external HDMI connected.
120          */
121         return NOTIFY_BAD;
122     }
123 
124     return NOTIFY_DONE;
125 }
126 
127 NV_STATUS NV_API_CALL nv_acpi_get_powersource(NvU32 *ac_plugged)
128 {
129     unsigned long long val;
130     int status = 0;
131 
132     if (!ac_plugged)
133         return NV_ERR_INVALID_ARGUMENT;
134 
135     if (!psr_device_handle)
136         return NV_ERR_INVALID_ARGUMENT;
137 
138     // Check whether or not AC power is plugged in
139     status = acpi_evaluate_integer(psr_device_handle, "_PSR", NULL, &val);
140     if (ACPI_FAILURE(status))
141         return NV_ERR_GENERIC;
142 
143     // AC Power Source Plug State
144     //  - 0x0 unplugged
145     //  - 0x1 plugged
146     *ac_plugged = (val == 0x1);
147 
148     return NV_OK;
149 }
150 
151 #define ACPI_POWER_SOURCE_CHANGE_EVENT       0x80
152 static void nv_acpi_powersource_hotplug_event(acpi_handle handle, u32 event_type, void *data)
153 {
154     /*
155      * This function will handle acpi events from the linux kernel, used
156      * to detect notifications from Power Source device
157      */
158     nv_acpi_t *pNvAcpiObject = data;
159     u32 ac_plugged = 0;
160 
161     if (event_type == ACPI_POWER_SOURCE_CHANGE_EVENT)
162     {
163         if (nv_acpi_get_powersource(&ac_plugged) != NV_OK)
164             return;
165 
166         rm_power_source_change_event(pNvAcpiObject->sp, !ac_plugged);
167     }
168 }
169 
170 static void nv_acpi_nvpcf_event(acpi_handle handle, u32 event_type, void *data)
171 {
172     nv_acpi_t *pNvAcpiObject = data;
173 
174     if (event_type == ACPI_NVPCF_EVENT_CHANGE)
175     {
176         rm_acpi_nvpcf_notify(pNvAcpiObject->sp);
177     }
178     else
179     {
180         nv_printf(NV_DBG_INFO,"NVRM: %s: NVPCF event 0x%x is not supported\n", event_type, __FUNCTION__);
181     }
182 }
183 
184 /*
185  * End of ACPI event handler functions
186  */
187 
188 /* Do the necessary allocations and install notifier "handler" on the device-node "device" */
189 static nv_acpi_t* nv_install_notifier(
190     struct acpi_handle *handle,
191     acpi_notify_handler handler,
192     void               *notifier_data
193 )
194 {
195     nvidia_stack_t *sp = NULL;
196     nv_acpi_t *pNvAcpiObject = NULL;
197     NV_STATUS rmStatus = NV_ERR_GENERIC;
198     acpi_status status = -1;
199 
200     if (!handle)
201         return NULL;
202 
203     if (nv_kmem_cache_alloc_stack(&sp) != 0)
204     {
205         return NULL;
206     }
207 
208     rmStatus = os_alloc_mem((void **) &pNvAcpiObject, sizeof(nv_acpi_t));
209     if (rmStatus != NV_OK)
210         goto return_error;
211 
212     os_mem_set((void *)pNvAcpiObject, 0, sizeof(nv_acpi_t));
213 
214     // store a handle reference in our object
215     pNvAcpiObject->handle = handle;
216     pNvAcpiObject->sp = sp;
217     pNvAcpiObject->notifier_data = notifier_data;
218 
219     status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
220               handler, pNvAcpiObject);
221     if (!ACPI_FAILURE(status))
222     {
223         pNvAcpiObject->notify_handler_installed = 1;
224 
225         return pNvAcpiObject;
226     }
227 
228 return_error:
229      nv_kmem_cache_free_stack(sp);
230      if (pNvAcpiObject)
231          os_free_mem((void *)pNvAcpiObject);
232 
233      return NULL;
234 }
235 
236 /* Tear-down and remove whatever nv_install_notifier did */
237 static void nv_uninstall_notifier(nv_acpi_t *pNvAcpiObject, acpi_notify_handler handler)
238 {
239     acpi_status status;
240 
241     if (pNvAcpiObject && pNvAcpiObject->notify_handler_installed)
242     {
243         status = acpi_remove_notify_handler(pNvAcpiObject->handle, ACPI_DEVICE_NOTIFY, handler);
244         if (ACPI_FAILURE(status))
245         {
246             nv_printf(NV_DBG_INFO,
247                 "NVRM: nv_acpi_methods_uninit: failed to remove event notification handler (%d)!\n", status);
248         }
249         else
250         {
251             nv_kmem_cache_free_stack(pNvAcpiObject->sp);
252             os_free_mem((void *)pNvAcpiObject);
253         }
254     }
255 
256     return;
257 }
258 
259 static void nv_acpi_notify_event(acpi_handle handle, u32 event_type, void *data)
260 {
261     nv_acpi_t  *pNvAcpiObject = data;
262     nv_state_t *nvl = pNvAcpiObject->notifier_data;
263 
264     /*
265      * Function to handle device specific ACPI events such as display hotplug,
266      * GPS and D-notifier events.
267      */
268     rm_acpi_notify(pNvAcpiObject->sp, NV_STATE_PTR(nvl), event_type);
269 }
270 
271 void nv_acpi_register_notifier(nv_linux_state_t *nvl)
272 {
273     acpi_handle dev_handle  = NULL;
274 
275     /* Install the ACPI notifier corresponding to dGPU ACPI device. */
276     if ((nvl->nv_acpi_object == NULL) &&
277         nv_acpi_get_device_handle(NV_STATE_PTR(nvl), &dev_handle) &&
278         (dev_handle != NULL))
279     {
280         nvl->nv_acpi_object = nv_install_notifier(dev_handle, nv_acpi_notify_event, nvl);
281         if (nvl->nv_acpi_object == NULL)
282         {
283             nv_printf(NV_DBG_ERRORS,
284                 "NVRM: nv_acpi_register_notifier: failed to install notifier\n");
285         }
286     }
287 
288     nvl->acpi_nb.notifier_call = nv_acpi_notifier_call_chain_handler;
289     register_acpi_notifier(&nvl->acpi_nb);
290 }
291 
292 void nv_acpi_unregister_notifier(nv_linux_state_t *nvl)
293 {
294     unregister_acpi_notifier(&nvl->acpi_nb);
295     if (nvl->nv_acpi_object != NULL)
296     {
297         nv_uninstall_notifier(nvl->nv_acpi_object, nv_acpi_notify_event);
298         nvl->nv_acpi_object = NULL;
299     }
300 }
301 
302 /*
303  * acpi methods init function.
304  * check if the NVIF, _DSM and WMMX methods are present in the acpi namespace.
305  * store NVIF, _DSM and WMMX handle if found.
306  */
307 
308 void NV_API_CALL nv_acpi_methods_init(NvU32 *handlesPresent)
309 {
310     if (!handlesPresent) // Caller passed us invalid pointer.
311         return;
312 
313     *handlesPresent = 0;
314 
315     NV_ACPI_WALK_NAMESPACE(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
316                         ACPI_UINT32_MAX, nv_acpi_find_methods, NULL, NULL);
317 
318     if (nvif_handle)
319     {
320         *handlesPresent = NV_ACPI_NVIF_HANDLE_PRESENT;
321     }
322 
323     if (wmmx_handle)
324         *handlesPresent = *handlesPresent | NV_ACPI_WMMX_HANDLE_PRESENT;
325 
326     if (psr_handle)
327     {
328         // Since _PSR is not a per-GPU construct we only need to register a
329         // single notifier for the _PSR event. Skip registration for subsequent
330         // devices
331         if (psr_nv_acpi_object == NULL)
332         {
333             psr_nv_acpi_object = nv_install_notifier(psr_device_handle, nv_acpi_powersource_hotplug_event, NULL);
334         }
335     }
336 
337     if (nvpcf_handle && (nvpcf_nv_acpi_object == NULL))
338     {
339         nvpcf_nv_acpi_object = nv_install_notifier(nvpcf_device_handle, nv_acpi_nvpcf_event, NULL);
340     }
341 
342     return;
343 }
344 
345 acpi_status nv_acpi_find_methods(
346     acpi_handle handle,
347     u32 nest_level,
348     void *dummy1,
349     void **dummy2
350 )
351 {
352     acpi_handle method_handle;
353 
354     if (!acpi_get_handle(handle, "NVIF", &method_handle))
355     {
356         nvif_handle = method_handle;
357     }
358 
359     if (!acpi_get_handle(handle, "WMMX", &method_handle))
360     {
361         wmmx_handle = method_handle;
362     }
363 
364     if (!acpi_get_handle(handle, "_PSR", &method_handle))
365     {
366         psr_handle = method_handle;
367         psr_device_handle = handle;
368     }
369 
370     if (!acpi_get_handle(handle, "NPCF", &method_handle))
371     {
372         nvpcf_handle = method_handle;
373         nvpcf_device_handle = handle;
374     }
375 
376     return 0;
377 }
378 
379 void NV_API_CALL nv_acpi_methods_uninit(void)
380 {
381     nvif_handle = NULL;
382     wmmx_handle = NULL;
383 
384     if (psr_nv_acpi_object != NULL)
385     {
386         nv_uninstall_notifier(psr_nv_acpi_object, nv_acpi_powersource_hotplug_event);
387 
388         psr_handle = NULL;
389         psr_device_handle = NULL;
390         psr_nv_acpi_object = NULL;
391     }
392 
393     if (nvpcf_nv_acpi_object != NULL)
394     {
395         nv_uninstall_notifier(nvpcf_nv_acpi_object, nv_acpi_nvpcf_event);
396 
397         nvpcf_handle = NULL;
398         nvpcf_device_handle = NULL;
399         nvpcf_nv_acpi_object = NULL;
400     }
401 }
402 
403 static NV_STATUS nv_acpi_extract_integer(
404     const union acpi_object *acpi_object,
405     void  *buffer,
406     NvU32  buffer_size,
407     NvU32 *data_size
408 )
409 {
410     if (acpi_object->type != ACPI_TYPE_INTEGER)
411         return NV_ERR_INVALID_ARGUMENT;
412 
413     if (acpi_object->integer.value & ~0xffffffffULL)
414         *data_size = sizeof(acpi_object->integer.value);
415     else
416         *data_size = sizeof(NvU32);
417 
418     if ((buffer_size < sizeof(NvU32)) ||
419         ((buffer_size < sizeof(acpi_object->integer.value)) &&
420          (acpi_object->integer.value & ~0xffffffffULL)))
421     {
422         return NV_ERR_BUFFER_TOO_SMALL;
423     }
424 
425     memcpy(buffer, &acpi_object->integer.value, *data_size);
426 
427     return NV_OK;
428 }
429 
430 static NV_STATUS nv_acpi_extract_buffer(
431     const union acpi_object *acpi_object,
432     void  *buffer,
433     NvU32  buffer_size,
434     NvU32 *data_size
435 )
436 {
437     if (acpi_object->type != ACPI_TYPE_BUFFER)
438         return NV_ERR_INVALID_ARGUMENT;
439 
440     *data_size = acpi_object->buffer.length;
441 
442     if (buffer_size < acpi_object->buffer.length)
443         return NV_ERR_BUFFER_TOO_SMALL;
444 
445     memcpy(buffer, acpi_object->buffer.pointer, *data_size);
446 
447     return NV_OK;
448 }
449 
450 static NV_STATUS nv_acpi_extract_package(
451     const union acpi_object *acpi_object,
452     void  *buffer,
453     NvU32  buffer_size,
454     NvU32 *data_size
455 )
456 {
457     NV_STATUS status = NV_OK;
458     NvU32 i, element_size = 0;
459 
460     if (acpi_object->type != ACPI_TYPE_PACKAGE)
461         return NV_ERR_INVALID_ARGUMENT;
462 
463     *data_size = 0;
464     for (i = 0; i < acpi_object->package.count; i++)
465     {
466         buffer = ((char *)buffer + element_size);
467         buffer_size -= element_size;
468 
469         status = nv_acpi_extract_object(&acpi_object->package.elements[i],
470                                         buffer, buffer_size, &element_size);
471         if (status != NV_OK)
472             break;
473 
474         *data_size += element_size;
475     }
476 
477     return status;
478 }
479 
480 static NV_STATUS nv_acpi_extract_object(
481     const union acpi_object *acpi_object,
482     void  *buffer,
483     NvU32  buffer_size,
484     NvU32 *data_size
485 )
486 {
487     NV_STATUS status;
488 
489     switch (acpi_object->type)
490     {
491         case ACPI_TYPE_INTEGER:
492             status = nv_acpi_extract_integer(acpi_object, buffer,
493                     buffer_size, data_size);
494             break;
495 
496         case ACPI_TYPE_BUFFER:
497             status = nv_acpi_extract_buffer(acpi_object, buffer,
498                     buffer_size, data_size);
499             break;
500 
501         case ACPI_TYPE_PACKAGE:
502             status = nv_acpi_extract_package(acpi_object, buffer,
503                     buffer_size, data_size);
504             break;
505 
506         case ACPI_TYPE_ANY:
507             /*
508              * ACPI_TYPE_ANY is used to represent a NULL/Uninitialized object which is objectType 0
509              * in the ACPI SPEC. This should not be treated as error.
510              */
511             status = NV_OK;
512             break;
513 
514         default:
515             status = NV_ERR_NOT_SUPPORTED;
516     }
517 
518     return status;
519 }
520 
521 NV_STATUS NV_API_CALL nv_acpi_method(
522     NvU32 acpi_method,
523     NvU32 function,
524     NvU32 subFunction,
525     void  *inParams,
526     NvU16 inParamSize,
527     NvU32 *outStatus,
528     void  *outData,
529     NvU16 *outDataSize
530 )
531 {
532     NV_STATUS status;
533 
534     switch (acpi_method)
535     {
536         case NV_EVAL_ACPI_METHOD_NVIF:
537             status = nv_acpi_nvif_method(function,
538                                          subFunction,
539                                          inParams,
540                                          inParamSize,
541                                          outStatus,
542                                          outData,
543                                          outDataSize);
544             break;
545 
546         case NV_EVAL_ACPI_METHOD_WMMX:
547             status = nv_acpi_wmmx_method(function,  outData, outDataSize);
548             break;
549 
550         default:
551             status = NV_ERR_NOT_SUPPORTED;
552     }
553 
554     return status;
555 }
556 
557 /*
558  * This function executes an NVIF ACPI method.
559  */
560 static NV_STATUS nv_acpi_nvif_method(
561     NvU32 function,
562     NvU32 subFunction,
563     void  *inParams,
564     NvU16 inParamSize,
565     NvU32 *outStatus,
566     void  *outData,
567     NvU16 *outDataSize
568 )
569 {
570     acpi_status status;
571     struct acpi_object_list input;
572     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
573     union acpi_object *nvif = NULL;
574     union acpi_object nvif_params[3];
575     NvU16 localOutDataSize;
576     NvU8  localInParams[8];
577 
578     if (!nvif_handle)
579         return NV_ERR_NOT_SUPPORTED;
580 
581     if (!NV_MAY_SLEEP())
582     {
583 #if defined(DEBUG)
584         nv_printf(NV_DBG_ERRORS,
585             "NVRM: nv_acpi_nvif_method: invalid context!\n");
586 #endif
587         return NV_ERR_NOT_SUPPORTED;
588     }
589 
590     nvif_params[0].integer.type  =  ACPI_TYPE_INTEGER;
591     nvif_params[0].integer.value =  function;
592 
593     nvif_params[1].integer.type  =  ACPI_TYPE_INTEGER;
594     nvif_params[1].integer.value =  subFunction;
595 
596     nvif_params[2].buffer.type  =  ACPI_TYPE_BUFFER;
597 
598     if (inParams && (inParamSize > 0))
599     {
600         nvif_params[2].buffer.length  = inParamSize;
601         nvif_params[2].buffer.pointer = inParams;
602     }
603     else
604     {
605         memset(localInParams, 0, 8);
606         nvif_params[2].buffer.length  = 8;
607         nvif_params[2].buffer.pointer = localInParams;
608     }
609 
610     input.count = 3;
611     input.pointer = nvif_params;
612 
613     status = acpi_evaluate_object(nvif_handle, NULL, &input, &output);
614     if (ACPI_FAILURE(status))
615     {
616         nv_printf(NV_DBG_INFO,
617             "NVRM: nv_acpi_nvif_method: failed to get NVIF data, "
618             "status 0x%x, function 0x%x, subFunction 0x%x!\n",
619             status, function, subFunction);
620         return NV_ERR_GENERIC;
621     }
622 
623     nvif = output.pointer;
624     if (nvif && (nvif->type == ACPI_TYPE_BUFFER) && (nvif->buffer.length >= 4))
625     {
626         if (outStatus)
627         {
628             *outStatus = nvif->buffer.pointer[3] << 24 |
629                          nvif->buffer.pointer[2] << 16 |
630                          nvif->buffer.pointer[1] << 8  |
631                          nvif->buffer.pointer[0];
632         }
633 
634         if (outData && outDataSize)
635         {
636             localOutDataSize = nvif->buffer.length - 4;
637             if (localOutDataSize <= *outDataSize)
638             {
639                 *outDataSize = NV_MIN(*outDataSize, localOutDataSize);
640                 memcpy(outData, &nvif->buffer.pointer[4], *outDataSize);
641             }
642             else
643             {
644                 *outDataSize = localOutDataSize;
645                 kfree(output.pointer);
646                 return NV_ERR_BUFFER_TOO_SMALL;
647             }
648         }
649     }
650     else
651     {
652         nv_printf(NV_DBG_INFO,
653             "NVRM: nv_acpi_nvif_method: NVIF data invalid, function 0x%x, "
654             "subFunction 0x%x!\n", function, subFunction);
655         kfree(output.pointer);
656         return NV_ERR_GENERIC;
657     }
658 
659     kfree(output.pointer);
660     return NV_OK;
661 }
662 
663 #define MAX_INPUT_PARAM_SIZE     1024
664 /*
665  * This function executes a _DSM ACPI method.
666  */
667 NV_STATUS NV_API_CALL nv_acpi_dsm_method(
668     nv_state_t *nv,
669     NvU8  *pAcpiDsmGuid,
670     NvU32 acpiDsmRev,
671     NvBool acpiNvpcfDsmFunction,
672     NvU32 acpiDsmSubFunction,
673     void  *pInParams,
674     NvU16 inParamSize,
675     NvU32 *outStatus,
676     void  *pOutData,
677     NvU16 *pSize
678 )
679 {
680     NV_STATUS status = NV_ERR_OPERATING_SYSTEM;
681     acpi_status acpi_status;
682     struct acpi_object_list input;
683     union acpi_object *dsm = NULL;
684     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
685     union acpi_object dsm_params[4];
686     NvU8 *argument3 = NULL;
687     NvU32 data_size;
688     acpi_handle dev_handle  = NULL;
689 
690     if (!nv_acpi_get_device_handle(nv, &dev_handle))
691         return NV_ERR_NOT_SUPPORTED;
692 
693     if (!dev_handle)
694         return NV_ERR_INVALID_ARGUMENT;
695 
696     if ((!pInParams) || (inParamSize > MAX_INPUT_PARAM_SIZE) || (!pOutData) || (!pSize))
697     {
698         nv_printf(NV_DBG_INFO,
699                   "NVRM: %s: invalid argument(s)!\n", __FUNCTION__);
700         return NV_ERR_INVALID_ARGUMENT;
701     }
702 
703     if (!NV_MAY_SLEEP())
704     {
705 #if defined(DEBUG)
706         nv_printf(NV_DBG_INFO,
707                   "NVRM: %s: invalid argument(s)!\n", __FUNCTION__);
708 #endif
709         return NV_ERR_NOT_SUPPORTED;
710     }
711 
712     status = os_alloc_mem((void **)&argument3, inParamSize);
713     if (status != NV_OK)
714         return status;
715 
716     //
717     // dsm_params[0].buffer.pointer and dsm_params[1].integer.value set in
718     // switch below based on acpiDsmFunction
719     //
720 
721     dsm_params[0].buffer.type    = ACPI_TYPE_BUFFER;
722     dsm_params[0].buffer.length  = 0x10;
723     dsm_params[0].buffer.pointer = pAcpiDsmGuid;
724 
725     dsm_params[1].integer.type   = ACPI_TYPE_INTEGER;
726     dsm_params[1].integer.value  = acpiDsmRev;
727 
728     dsm_params[2].integer.type   = ACPI_TYPE_INTEGER;
729     dsm_params[2].integer.value  = acpiDsmSubFunction;
730 
731     dsm_params[3].buffer.type    = ACPI_TYPE_BUFFER;
732     dsm_params[3].buffer.length  = inParamSize;
733     memcpy(argument3, pInParams, dsm_params[3].buffer.length);
734     dsm_params[3].buffer.pointer = argument3;
735 
736     // parameters for dsm calls (GUID, rev, subfunction, data)
737     input.count = 4;
738     input.pointer = dsm_params;
739 
740     if (acpiNvpcfDsmFunction)
741     {
742         //
743         // acpi_evaluate_object() can operate with either valid object pathname or
744         // valid object handle. For NVPCF DSM function, use valid pathname as we do
745         // not have device handle for NVPCF device
746         //
747         dev_handle = NULL;
748         acpi_status = acpi_evaluate_object(dev_handle, "\\_SB.NPCF._DSM", &input, &output);
749     }
750     else
751     {
752         acpi_status = acpi_evaluate_object(dev_handle, "_DSM", &input, &output);
753     }
754 
755     if (ACPI_FAILURE(acpi_status))
756     {
757         nv_printf(NV_DBG_INFO,
758               "NVRM: %s: failed to evaluate _DSM method!\n", __FUNCTION__);
759         goto exit;
760     }
761 
762     dsm = output.pointer;
763     if (dsm != NULL)
764     {
765         if (outStatus)
766         {
767             *outStatus = dsm->buffer.pointer[3] << 24 |
768                          dsm->buffer.pointer[2] << 16 |
769                          dsm->buffer.pointer[1] << 8  |
770                          dsm->buffer.pointer[0];
771         }
772 
773         status = nv_acpi_extract_object(dsm, pOutData, *pSize, &data_size);
774         *pSize = data_size;
775 
776         kfree(output.pointer);
777     }
778     if (status != NV_OK)
779     {
780         nv_printf(NV_DBG_ERRORS,
781                   "NVRM: %s: DSM data invalid!\n", __FUNCTION__);
782     }
783 
784 exit:
785     os_free_mem(argument3);
786     return status;
787 }
788 
789 /*
790  * This function executes a _DDC ACPI method.
791  */
792 NV_STATUS NV_API_CALL nv_acpi_ddc_method(
793     nv_state_t *nv,
794     void *pEdidBuffer,
795     NvU32 *pSize,
796     NvBool bReadMultiBlock
797 )
798 {
799     acpi_status status;
800     union acpi_object *ddc = NULL;
801     NvU32 i, largestEdidSize;
802     acpi_handle dev_handle  = NULL;
803     acpi_handle lcd_dev_handle  = NULL;
804     acpi_handle handle = NULL;
805 
806     if (!nv_acpi_get_device_handle(nv, &dev_handle))
807         return NV_ERR_NOT_SUPPORTED;
808 
809     if (!dev_handle)
810         return NV_ERR_INVALID_ARGUMENT;
811 
812     if (!NV_MAY_SLEEP())
813     {
814 #if defined(DEBUG)
815         nv_printf(NV_DBG_ERRORS,
816                   "NVRM: %s: invalid context!\n",
817                   __FUNCTION__);
818 #endif
819         return NV_ERR_NOT_SUPPORTED;
820     }
821 
822     while (lcd_dev_handle == NULL)
823     {
824         unsigned long long device_id = 0;
825 
826         status = acpi_get_next_object(ACPI_TYPE_DEVICE, dev_handle,
827                                       handle, &handle);
828         if (ACPI_FAILURE(status) || (handle == NULL))
829             break;
830 
831         status = acpi_evaluate_integer(handle, "_ADR", NULL, &device_id);
832         if (ACPI_FAILURE(status))
833             /* Couldnt query device_id for this device */
834             continue;
835 
836         switch (device_id & 0xffff) {
837             case 0x0110:
838             case 0x0118:
839             case 0x0400:
840             case 0xA420:
841                 lcd_dev_handle = handle;
842                 nv_printf(NV_DBG_INFO, "NVRM: %s Found LCD: %x\n",
843                           __FUNCTION__, device_id);
844                 break;
845             default:
846                 break;
847         }
848     }
849 
850     if (lcd_dev_handle == NULL)
851     {
852         nv_printf(NV_DBG_INFO, "NVRM: %s LCD not found\n", __FUNCTION__);
853         return NV_ERR_GENERIC;
854     }
855 
856     //
857     // As per ACPI Spec 3.0:
858     // ARG0 = 0x1 for 128 bytes edid buffer
859     // ARG0 = 0x2 for 256 bytes edid buffer
860     //
861 
862     largestEdidSize = bReadMultiBlock ? 2 : 1;
863 
864     for (i = largestEdidSize; i >= 1; i--)
865     {
866         struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
867         union acpi_object ddc_arg0 = { ACPI_TYPE_INTEGER };
868         struct acpi_object_list input = { 1, &ddc_arg0 };
869 
870         ddc_arg0.integer.value = i;
871         status = acpi_evaluate_object(lcd_dev_handle, "_DDC", &input, &output);
872         if (ACPI_SUCCESS(status)) {
873             ddc = output.pointer;
874             break;
875         }
876     }
877 
878     if (ACPI_FAILURE(status))
879     {
880         nv_printf(NV_DBG_INFO,
881                   "NVRM: %s: failed status: %08x \n",
882                   __FUNCTION__,
883                   status);
884         return NV_ERR_GENERIC;
885     }
886     else
887     {
888         if (ddc && (ddc->type == ACPI_TYPE_BUFFER) && (ddc->buffer.length > 0))
889         {
890             if (ddc->buffer.length <= *pSize)
891             {
892                 *pSize = NV_MIN(*pSize, ddc->buffer.length);
893                 memcpy(pEdidBuffer, ddc->buffer.pointer, *pSize);
894             }
895             else
896             {
897                 kfree(ddc);
898                 return NV_ERR_BUFFER_TOO_SMALL;
899             }
900         }
901     }
902 
903     kfree(ddc);
904     return NV_OK;
905 }
906 
907 /*
908  * This function executes a _ROM ACPI method.
909  */
910 NV_STATUS NV_API_CALL nv_acpi_rom_method(
911     nv_state_t *nv,
912     NvU32 *pInData,
913     NvU32 *pOutData
914 )
915 {
916     acpi_status status;
917     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
918     union acpi_object *rom;
919     union acpi_object rom_arg[2];
920     struct acpi_object_list input = { 2, rom_arg };
921     acpi_handle dev_handle  = NULL;
922     uint32_t offset, length;
923 
924     if (!nv_acpi_get_device_handle(nv, &dev_handle))
925         return NV_ERR_NOT_SUPPORTED;
926 
927     if (!dev_handle)
928         return NV_ERR_INVALID_ARGUMENT;
929 
930     if (!NV_MAY_SLEEP())
931     {
932 #if defined(DEBUG)
933         nv_printf(NV_DBG_ERRORS,
934                   "NVRM: %s: invalid context!\n", __FUNCTION__);
935 #endif
936         return NV_ERR_NOT_SUPPORTED;
937     }
938 
939     offset = pInData[0];
940     length = pInData[1];
941 
942     rom_arg[0].type = ACPI_TYPE_INTEGER;
943     rom_arg[0].integer.value = offset;
944     rom_arg[1].type = ACPI_TYPE_INTEGER;
945     rom_arg[1].integer.value = length;
946 
947     status = acpi_evaluate_object(dev_handle, "_ROM", &input, &output);
948     if (ACPI_FAILURE(status))
949     {
950         nv_printf(NV_DBG_INFO,
951               "NVRM: %s: failed to evaluate _ROM method!\n", __FUNCTION__);
952         return NV_ERR_GENERIC;
953     }
954     else
955     {
956         rom = output.pointer;
957 
958         if ((rom != NULL) && (rom->type == ACPI_TYPE_BUFFER) &&
959             (rom->buffer.length >= length))
960         {
961             memcpy(pOutData, rom->buffer.pointer, length);
962         }
963         else
964         {
965             nv_printf(NV_DBG_INFO,
966                   "NVRM: %s: Invalid _ROM data\n", __FUNCTION__);
967             kfree(output.pointer);
968             return NV_ERR_GENERIC;
969         }
970     }
971 
972     kfree(output.pointer);
973     return NV_OK;
974 }
975 
976 /*
977  * This function executes a _DOD ACPI method.
978  */
979 NV_STATUS NV_API_CALL nv_acpi_dod_method(
980     nv_state_t *nv,
981     NvU32      *pOutData,
982     NvU32      *pSize
983 )
984 {
985     acpi_status status;
986     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
987     union acpi_object *dod;
988     acpi_handle dev_handle = NULL;
989     NvU32 i, count = (*pSize / sizeof(NvU32));
990 
991     if (!nv_acpi_get_device_handle(nv, &dev_handle))
992         return NV_ERR_NOT_SUPPORTED;
993 
994     if (!dev_handle)
995         return NV_ERR_INVALID_ARGUMENT;
996 
997     if (!NV_MAY_SLEEP())
998     {
999 #if defined(DEBUG)
1000         nv_printf(NV_DBG_ERRORS,
1001               "NVRM: %s: invalid context!\n", __FUNCTION__);
1002 #endif
1003         return NV_ERR_NOT_SUPPORTED;
1004     }
1005 
1006     status = acpi_evaluate_object(dev_handle, "_DOD", NULL, &output);
1007 
1008     if (ACPI_FAILURE(status))
1009     {
1010         nv_printf(NV_DBG_INFO,
1011               "NVRM: %s: failed to evaluate _DOD method!\n", __FUNCTION__);
1012         return NV_ERR_GENERIC;
1013     }
1014     else
1015     {
1016         dod = output.pointer;
1017         *pSize = 0;
1018 
1019         if ((dod != NULL) && (dod->type == ACPI_TYPE_PACKAGE) &&
1020             (dod->package.count <= count))
1021         {
1022             for (i = 0; i < dod->package.count; i++)
1023             {
1024                 if (dod->package.elements[i].type != ACPI_TYPE_INTEGER)
1025                 {
1026                     nv_printf(NV_DBG_INFO,
1027                             "NVRM: %s: _DOD entry invalid!\n", __FUNCTION__);
1028                     kfree(output.pointer);
1029                     return NV_ERR_GENERIC;
1030                 }
1031 
1032                 pOutData[i] = dod->package.elements[i].integer.value;
1033                 *pSize += sizeof(NvU32);
1034             }
1035         }
1036         else
1037         {
1038             nv_printf(NV_DBG_INFO,
1039                       "NVRM: %s: _DOD data too large!\n", __FUNCTION__);
1040             kfree(output.pointer);
1041             return NV_ERR_GENERIC;
1042         }
1043     }
1044 
1045     kfree(output.pointer);
1046     return NV_OK;
1047 }
1048 
1049 /*
1050  * This function executes a WMMX ACPI method.
1051  */
1052 static NV_STATUS  nv_acpi_wmmx_method(
1053     NvU32 arg2,
1054     NvU8  *outData,
1055     NvU16 *outDataSize
1056 )
1057 {
1058     acpi_status status;
1059     struct acpi_object_list input;
1060     struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1061     union acpi_object *mmx = NULL;
1062     union acpi_object mmx_params[3];
1063 
1064     if (!wmmx_handle)
1065         return NV_ERR_NOT_SUPPORTED;
1066 
1067     if (!NV_MAY_SLEEP())
1068     {
1069 #if defined(DEBUG)
1070         nv_printf(NV_DBG_ERRORS,
1071             "NVRM: nv_acpi_wmmx_method: invalid context!\n");
1072 #endif
1073         return NV_ERR_NOT_SUPPORTED;
1074     }
1075 
1076    /* argument 0 and argument 1 are not used in WMMX method, passing 0 */
1077 
1078     mmx_params[0].integer.type  =  ACPI_TYPE_INTEGER;
1079     mmx_params[0].integer.value =  0;
1080 
1081     mmx_params[1].integer.type  =  ACPI_TYPE_INTEGER;
1082     mmx_params[1].integer.value =  0;
1083 
1084     mmx_params[2].integer.type  =  ACPI_TYPE_INTEGER;
1085     mmx_params[2].integer.value =  arg2;
1086 
1087     input.count = 3;
1088     input.pointer = mmx_params;
1089 
1090     status = acpi_evaluate_object(wmmx_handle, NULL, &input, &output);
1091     if (ACPI_FAILURE(status))
1092     {
1093         nv_printf(NV_DBG_INFO,
1094             "NVRM: nv_acpi_wmmx_method: failed to get WMMX data, "
1095             "status 0x%x!\n", status);
1096         return NV_ERR_GENERIC;
1097     }
1098 
1099     mmx = output.pointer;
1100     if (mmx && (mmx->type == ACPI_TYPE_BUFFER) && (mmx->buffer.length > 0))
1101     {
1102         if (outData && outDataSize)
1103         {
1104             if (mmx->buffer.length <= *outDataSize)
1105             {
1106                 *outDataSize = NV_MIN(*outDataSize, mmx->buffer.length);
1107                 memcpy(outData, mmx->buffer.pointer, *outDataSize);
1108             }
1109             else
1110             {
1111                 kfree(output.pointer);
1112                 return NV_ERR_BUFFER_TOO_SMALL;
1113             }
1114         }
1115     }
1116     else
1117     {
1118         nv_printf(NV_DBG_ERRORS,
1119                 "NVRM: nv_acpi_wmmx_method: WMMX data invalid.\n");
1120         kfree(output.pointer);
1121         return NV_ERR_GENERIC;
1122     }
1123 
1124     kfree(output.pointer);
1125     return NV_OK;
1126 }
1127 
1128 NvBool nv_acpi_power_resource_method_present(
1129     struct pci_dev *pdev
1130 )
1131 {
1132     acpi_handle handle = NULL;
1133     struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
1134     union acpi_object *object_package, *object_reference;
1135     acpi_status status;
1136 
1137 #if defined(DEVICE_ACPI_HANDLE)
1138     handle = DEVICE_ACPI_HANDLE(&pdev->dev);
1139 #elif defined (ACPI_HANDLE)
1140     handle = ACPI_HANDLE(&pdev->dev);
1141 #endif
1142 
1143     if (!handle)
1144         return NV_FALSE;
1145 
1146     status = acpi_evaluate_object(handle, "_PR3", NULL, &buf);
1147     if (ACPI_FAILURE(status))
1148     {
1149         nv_printf(NV_DBG_INFO,"NVRM: Failed to evaluate _PR3 object\n");
1150         return NV_FALSE;
1151     }
1152 
1153     if (!buf.pointer)
1154     {
1155        nv_printf(NV_DBG_INFO, "NVRM: output buffer pointer is null"
1156                               " for _PR3 method\n");
1157        return NV_FALSE;
1158     }
1159 
1160     object_package = buf.pointer;
1161 
1162     /*
1163      * _PR3 object should be of type package and
1164      * it should contain only one reference
1165      */
1166     if ((object_package->type != ACPI_TYPE_PACKAGE) &&
1167         (object_package->package.count != 0x1))
1168     {
1169         nv_printf(NV_DBG_ERRORS,"NVRM: _PR3 object is not a type 'package'\n");
1170         return NV_FALSE;
1171     }
1172 
1173     object_reference = object_package->package.elements;
1174 
1175     /* Check for the reference and the actual type of the reference. */
1176     if ((object_reference->reference.actual_type != ACPI_TYPE_POWER) &&
1177         (object_reference->type !=  ACPI_TYPE_LOCAL_REFERENCE))
1178     {
1179         nv_printf(NV_DBG_ERRORS,
1180                      "NVRM: _PR3 object does not contain POWER Reference\n");
1181         return NV_FALSE;
1182     }
1183     return NV_TRUE;
1184 }
1185 
1186 /*
1187  * This function executes MUX ACPI methods.
1188  */
1189 NV_STATUS NV_API_CALL nv_acpi_mux_method(
1190     nv_state_t *nv,
1191     NvU32 *pInOut,
1192     NvU32 muxAcpiId,
1193     const char *pMethodName
1194 )
1195 {
1196     acpi_status status;
1197     struct acpi_buffer output     = { ACPI_ALLOCATE_BUFFER, NULL };
1198     union acpi_object *mux        = NULL;
1199     union acpi_object mux_arg     = { ACPI_TYPE_INTEGER };
1200     struct acpi_object_list input = { 1, &mux_arg };
1201     acpi_handle dev_handle        = NULL;
1202     acpi_handle mux_dev_handle    = NULL;
1203     acpi_handle handle            = NULL;
1204     unsigned long long device_id  = 0;
1205 
1206     if ((strcmp(pMethodName, "MXDS") != 0)
1207         && (strcmp(pMethodName, "MXDM") != 0))
1208     {
1209         nv_printf(NV_DBG_ERRORS, "NVRM: %s: Unsupported ACPI method %s\n",
1210                   __FUNCTION__, pMethodName);
1211         return NV_ERR_NOT_SUPPORTED;
1212     }
1213     else
1214     {
1215         nv_printf(NV_DBG_INFO, "NVRM: %s: Call for %s ACPI method \n",
1216                   __FUNCTION__, pMethodName);
1217     }
1218 
1219     if (!nv_acpi_get_device_handle(nv, &dev_handle))
1220         return NV_ERR_NOT_SUPPORTED;
1221 
1222     if (!dev_handle)
1223         return NV_ERR_INVALID_ARGUMENT;
1224 
1225     if (!NV_MAY_SLEEP())
1226     {
1227 #if defined(DEBUG)
1228         nv_printf(NV_DBG_ERRORS, "NVRM: %s: invalid context!\n", __FUNCTION__);
1229 #endif
1230         return NV_ERR_NOT_SUPPORTED;
1231     }
1232 
1233     while (mux_dev_handle == NULL)
1234     {
1235         status = acpi_get_next_object(ACPI_TYPE_DEVICE, dev_handle,
1236                                       handle, &handle);
1237         if (ACPI_FAILURE(status) || (handle == NULL))
1238             break;
1239 
1240         status = acpi_evaluate_integer(handle, "_ADR", NULL, &device_id);
1241         if (ACPI_SUCCESS(status) && (device_id == muxAcpiId))
1242             mux_dev_handle = handle;
1243     }
1244 
1245     if (mux_dev_handle == NULL)
1246     {
1247         nv_printf(NV_DBG_INFO,
1248                   "NVRM: %s Mux device handle not found\n", __FUNCTION__);
1249         return NV_ERR_GENERIC;
1250     }
1251 
1252     mux_arg.integer.type = ACPI_TYPE_INTEGER;
1253     mux_arg.integer.value = (NvU64) *pInOut;
1254 
1255     status = acpi_evaluate_object(mux_dev_handle, (acpi_string)pMethodName,
1256                                   &input, &output);
1257 
1258     if (ACPI_FAILURE(status))
1259     {
1260         nv_printf(NV_DBG_INFO, "NVRM: %s: Failed to evaluate %s method!\n",
1261                   __FUNCTION__, pMethodName);
1262         return NV_ERR_GENERIC;
1263     }
1264     else
1265     {
1266         mux = output.pointer;
1267 
1268         if (mux && (mux->type == ACPI_TYPE_INTEGER))
1269         {
1270             *pInOut = mux->integer.value;
1271         }
1272         else
1273         {
1274             nv_printf(NV_DBG_INFO,
1275                       "NVRM: %s: Invalid MUX data\n", __FUNCTION__);
1276             kfree(output.pointer);
1277             return NV_ERR_GENERIC;
1278         }
1279     }
1280 
1281     kfree(output.pointer);
1282     return NV_OK;
1283 }
1284 
1285 static acpi_status nv_acpi_find_battery_info(
1286     acpi_handle handle,
1287     NvBool bUseBix
1288 )
1289 {
1290     acpi_status status = AE_OK;
1291     struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
1292     union acpi_object *object_package;
1293     NvU32 battery_technology_offset;
1294 
1295     status = acpi_evaluate_object(handle, NULL, NULL, &buf);
1296 
1297     if (ACPI_FAILURE(status))
1298     {
1299         nv_printf(NV_DBG_INFO, "NVRM: Failed to evaluate battery's object\n");
1300         return AE_OK;
1301     }
1302 
1303     if (!buf.pointer)
1304     {
1305         nv_printf(NV_DBG_INFO, "NVRM: Battery object output buffer is null\n");
1306         return AE_OK;
1307     }
1308 
1309     object_package = buf.pointer;
1310 
1311     if (object_package->type != ACPI_TYPE_PACKAGE)
1312     {
1313         nv_printf(NV_DBG_INFO, "NVRM: Battery method output is not package\n");
1314         return AE_OK;
1315     }
1316 
1317     if (bUseBix)
1318     {
1319         battery_technology_offset = BIX_BATTERY_TECHNOLOGY_OFFSET;
1320     }
1321     else
1322     {
1323         battery_technology_offset = BIF_BATTERY_TECHNOLOGY_OFFSET;
1324     }
1325 
1326     /*
1327      * Only checking here for Battery technology type.
1328      * Other fields like Battery Model/Serial number could also be checked but
1329      * driver need to support the case where user has removed battery from the
1330      * system.
1331      * _STA method on the battery device handle couldn't be used due to the same
1332      * reason.
1333      * Hence just cheking if battery technology of slot is rechargable or not.
1334      */
1335 
1336     if ((object_package->package.elements[battery_technology_offset].type != ACPI_TYPE_INTEGER) ||
1337         (object_package->package.elements[battery_technology_offset].integer.value != BATTERY_RECHARGABLE))
1338     {
1339         return AE_OK;
1340     }
1341 
1342     battery_present = NV_TRUE;
1343 
1344     /* Stop traversing acpi tree. */
1345     return AE_CTRL_TERMINATE;
1346 }
1347 
1348 static acpi_status nv_acpi_find_battery_device(
1349     acpi_handle handle,
1350     u32 nest_level,
1351     void *dummy1,
1352     void **dummy2
1353 )
1354 {
1355     acpi_handle bif_method_handle;
1356     acpi_handle bix_method_handle;
1357     acpi_status status = AE_OK;
1358 
1359     // Find method Battery Information /Extended/ (_BIX or _BIF) and then Battery type.
1360     if (!acpi_get_handle(handle, "_BIX", &bix_method_handle))
1361     {
1362         status = nv_acpi_find_battery_info(bix_method_handle, NV_TRUE/*bUseBix*/);
1363     }
1364 
1365     if ((battery_present == NV_FALSE) &&
1366         !acpi_get_handle(handle, "_BIF", &bif_method_handle))
1367     {
1368         status = nv_acpi_find_battery_info(bif_method_handle, NV_FALSE/*bUseBix*/);
1369     }
1370 
1371     return status;
1372 }
1373 
1374 NvBool NV_API_CALL nv_acpi_is_battery_present(void)
1375 {
1376     NV_ACPI_WALK_NAMESPACE(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
1377                            nv_acpi_find_battery_device, NULL, NULL);
1378 
1379     if (battery_present == NV_TRUE)
1380     {
1381         return NV_TRUE;
1382     }
1383 
1384     return NV_FALSE;
1385 }
1386 
1387 #else // NV_LINUX_ACPI_EVENTS_SUPPORTED
1388 
1389 void NV_API_CALL nv_acpi_methods_init(NvU32 *handlePresent)
1390 {
1391     *handlePresent = 0;
1392 }
1393 
1394 void NV_API_CALL nv_acpi_methods_uninit(void)
1395 {
1396     return;
1397 }
1398 
1399 NV_STATUS NV_API_CALL nv_acpi_method(
1400     NvU32 acpi_method,
1401     NvU32 function,
1402     NvU32 subFunction,
1403     void  *inParams,
1404     NvU16 inParamSize,
1405     NvU32 *outStatus,
1406     void  *outData,
1407     NvU16 *outDataSize
1408 )
1409 {
1410     return NV_ERR_NOT_SUPPORTED;
1411 }
1412 
1413 NV_STATUS NV_API_CALL nv_acpi_dsm_method(
1414     nv_state_t *nv,
1415     NvU8  *pAcpiDsmGuid,
1416     NvU32 acpiDsmRev,
1417     NvBool acpiNvpcfDsmFunction,
1418     NvU32 acpiDsmSubFunction,
1419     void  *pInParams,
1420     NvU16 inParamSize,
1421     NvU32 *outStatus,
1422     void  *pOutData,
1423     NvU16 *pSize
1424 )
1425 {
1426     return NV_ERR_NOT_SUPPORTED;
1427 }
1428 
1429 NV_STATUS NV_API_CALL nv_acpi_ddc_method(
1430     nv_state_t *nv,
1431     void *pEdidBuffer,
1432     NvU32 *pSize,
1433     NvBool bReadMultiBlock
1434 )
1435 {
1436     return NV_ERR_NOT_SUPPORTED;
1437 }
1438 
1439 NV_STATUS NV_API_CALL nv_acpi_rom_method(
1440     nv_state_t *nv,
1441     NvU32 *pInData,
1442     NvU32 *pOutData
1443 )
1444 {
1445     return NV_ERR_NOT_SUPPORTED;
1446 }
1447 
1448 NV_STATUS NV_API_CALL nv_acpi_dod_method(
1449     nv_state_t *nv,
1450     NvU32      *pOutData,
1451     NvU32      *pSize
1452 )
1453 {
1454     return NV_ERR_NOT_SUPPORTED;
1455 }
1456 
1457 NvBool nv_acpi_power_resource_method_present(
1458     struct pci_dev *pdev
1459 )
1460 {
1461     return NV_FALSE;
1462 }
1463 
1464 NV_STATUS NV_API_CALL nv_acpi_get_powersource(NvU32 *ac_plugged)
1465 {
1466     return NV_ERR_NOT_SUPPORTED;
1467 }
1468 
1469 void nv_acpi_register_notifier(nv_linux_state_t *nvl)
1470 {
1471     return;
1472 }
1473 
1474 void nv_acpi_unregister_notifier(nv_linux_state_t *nvl)
1475 {
1476     return;
1477 }
1478 
1479 NV_STATUS NV_API_CALL nv_acpi_mux_method(
1480     nv_state_t *nv,
1481     NvU32 *pInOut,
1482     NvU32 muxAcpiId,
1483     const char *pMethodName
1484 )
1485 {
1486     return NV_ERR_NOT_SUPPORTED;
1487 }
1488 
1489 NvBool NV_API_CALL nv_acpi_is_battery_present(void)
1490 {
1491     return NV_FALSE;
1492 }
1493 #endif
1494