Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/acpica/acpi_pci.c
39534 views
1
/*-
2
* Copyright (c) 1997, Stefan Esser <[email protected]>
3
* Copyright (c) 2000, Michael Smith <[email protected]>
4
* Copyright (c) 2000, BSDi
5
* All rights reserved.
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
* 1. Redistributions of source code must retain the above copyright
11
* notice unmodified, this list of conditions, and the following
12
* disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
#include <sys/cdefs.h>
30
#include "opt_acpi.h"
31
#include "opt_iommu.h"
32
33
#include <sys/param.h>
34
#include <sys/systm.h>
35
#include <sys/bus.h>
36
#include <sys/kernel.h>
37
#include <sys/malloc.h>
38
#include <sys/module.h>
39
#include <sys/sbuf.h>
40
#include <sys/taskqueue.h>
41
#include <sys/tree.h>
42
43
#include <contrib/dev/acpica/include/acpi.h>
44
#include <contrib/dev/acpica/include/accommon.h>
45
46
#include <dev/acpica/acpivar.h>
47
#include <dev/acpica/acpi_pcivar.h>
48
49
#include <sys/pciio.h>
50
#include <dev/pci/pcireg.h>
51
#include <dev/pci/pcivar.h>
52
#include <dev/pci/pci_private.h>
53
54
#include <dev/iommu/iommu.h>
55
56
/* Hooks for the ACPI CA debugging infrastructure. */
57
#define _COMPONENT ACPI_BUS
58
ACPI_MODULE_NAME("PCI")
59
60
struct acpi_pci_devinfo {
61
struct pci_devinfo ap_dinfo;
62
ACPI_HANDLE ap_handle;
63
int ap_flags;
64
};
65
66
ACPI_SERIAL_DECL(pci_powerstate, "ACPI PCI power methods");
67
68
/* Be sure that ACPI and PCI power states are equivalent. */
69
CTASSERT(ACPI_STATE_D0 == PCI_POWERSTATE_D0);
70
CTASSERT(ACPI_STATE_D1 == PCI_POWERSTATE_D1);
71
CTASSERT(ACPI_STATE_D2 == PCI_POWERSTATE_D2);
72
CTASSERT(ACPI_STATE_D3 == PCI_POWERSTATE_D3);
73
74
static struct pci_devinfo *acpi_pci_alloc_devinfo(device_t dev);
75
static int acpi_pci_attach(device_t dev);
76
static void acpi_pci_child_deleted(device_t dev, device_t child);
77
static int acpi_pci_child_location_method(device_t cbdev,
78
device_t child, struct sbuf *sb);
79
static int acpi_pci_get_device_path(device_t cbdev,
80
device_t child, const char *locator, struct sbuf *sb);
81
static int acpi_pci_detach(device_t dev);
82
static int acpi_pci_probe(device_t dev);
83
static int acpi_pci_read_ivar(device_t dev, device_t child, int which,
84
uintptr_t *result);
85
static int acpi_pci_write_ivar(device_t dev, device_t child, int which,
86
uintptr_t value);
87
static ACPI_STATUS acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level,
88
void *context, void **status);
89
static int acpi_pci_set_powerstate_method(device_t dev, device_t child,
90
int state);
91
static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child);
92
static bus_dma_tag_t acpi_pci_get_dma_tag(device_t bus, device_t child);
93
static int acpi_pci_get_domain(device_t dev, device_t child, int *domain);
94
95
static device_method_t acpi_pci_methods[] = {
96
/* Device interface */
97
DEVMETHOD(device_probe, acpi_pci_probe),
98
DEVMETHOD(device_attach, acpi_pci_attach),
99
DEVMETHOD(device_detach, acpi_pci_detach),
100
101
/* Bus interface */
102
DEVMETHOD(bus_read_ivar, acpi_pci_read_ivar),
103
DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar),
104
DEVMETHOD(bus_child_deleted, acpi_pci_child_deleted),
105
DEVMETHOD(bus_child_location, acpi_pci_child_location_method),
106
DEVMETHOD(bus_get_device_path, acpi_pci_get_device_path),
107
DEVMETHOD(bus_get_cpus, acpi_get_cpus),
108
DEVMETHOD(bus_get_dma_tag, acpi_pci_get_dma_tag),
109
DEVMETHOD(bus_get_domain, acpi_pci_get_domain),
110
111
/* PCI interface */
112
DEVMETHOD(pci_alloc_devinfo, acpi_pci_alloc_devinfo),
113
DEVMETHOD(pci_child_added, acpi_pci_child_added),
114
DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
115
116
DEVMETHOD_END
117
};
118
119
DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, sizeof(struct pci_softc),
120
pci_driver);
121
DRIVER_MODULE(acpi_pci, pcib, acpi_pci_driver, 0, 0);
122
MODULE_DEPEND(acpi_pci, acpi, 1, 1, 1);
123
MODULE_DEPEND(acpi_pci, pci, 1, 1, 1);
124
MODULE_VERSION(acpi_pci, 1);
125
126
static struct pci_devinfo *
127
acpi_pci_alloc_devinfo(device_t dev)
128
{
129
struct acpi_pci_devinfo *dinfo;
130
131
dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
132
return (&dinfo->ap_dinfo);
133
}
134
135
static int
136
acpi_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
137
{
138
struct acpi_pci_devinfo *dinfo;
139
140
dinfo = device_get_ivars(child);
141
switch (which) {
142
case ACPI_IVAR_HANDLE:
143
*result = (uintptr_t)dinfo->ap_handle;
144
return (0);
145
case ACPI_IVAR_FLAGS:
146
*result = (uintptr_t)dinfo->ap_flags;
147
return (0);
148
}
149
return (pci_read_ivar(dev, child, which, result));
150
}
151
152
static int
153
acpi_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
154
{
155
struct acpi_pci_devinfo *dinfo;
156
157
dinfo = device_get_ivars(child);
158
switch (which) {
159
case ACPI_IVAR_HANDLE:
160
dinfo->ap_handle = (ACPI_HANDLE)value;
161
return (0);
162
case ACPI_IVAR_FLAGS:
163
dinfo->ap_flags = (int)value;
164
return (0);
165
}
166
return (pci_write_ivar(dev, child, which, value));
167
}
168
169
static void
170
acpi_pci_child_deleted(device_t dev, device_t child)
171
{
172
struct acpi_pci_devinfo *dinfo = device_get_ivars(child);
173
174
if (acpi_get_device(dinfo->ap_handle) == child)
175
AcpiDetachData(dinfo->ap_handle, acpi_fake_objhandler);
176
pci_child_deleted(dev, child);
177
}
178
179
static int
180
acpi_pci_child_location_method(device_t cbdev, device_t child, struct sbuf *sb)
181
{
182
struct acpi_pci_devinfo *dinfo = device_get_ivars(child);
183
int pxm;
184
185
pci_child_location_method(cbdev, child, sb);
186
187
if (dinfo->ap_handle) {
188
sbuf_printf(sb, " handle=%s", acpi_name(dinfo->ap_handle));
189
if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ap_handle, "_PXM", &pxm))) {
190
sbuf_printf(sb, " _PXM=%d", pxm);
191
}
192
}
193
return (0);
194
}
195
196
static int
197
acpi_pci_get_device_path(device_t bus, device_t child, const char *locator, struct sbuf *sb)
198
{
199
200
if (strcmp(locator, BUS_LOCATOR_ACPI) == 0)
201
return (acpi_get_acpi_device_path(bus, child, locator, sb));
202
203
/* Otherwise follow base class' actions */
204
return (pci_get_device_path_method(bus, child, locator, sb));
205
}
206
207
/*
208
* Fetch the NUMA domain for the given device 'dev'.
209
*
210
* If a device has a _PXM method, map that to a NUMA domain.
211
* Otherwise, pass the request up to the parent.
212
* If there's no matching domain or the domain cannot be
213
* determined, return ENOENT.
214
*/
215
static int
216
acpi_pci_get_domain(device_t dev, device_t child, int *domain)
217
{
218
int d;
219
220
d = acpi_pxm_parse(child);
221
if (d >= 0) {
222
*domain = d;
223
return (0);
224
}
225
if (d == -1)
226
return (ENOENT);
227
228
/* No _PXM node; go up a level */
229
return (bus_generic_get_domain(dev, child, domain));
230
}
231
232
/*
233
* PCI power manangement
234
*/
235
static int
236
acpi_pci_set_powerstate_method(device_t dev, device_t child, int state)
237
{
238
ACPI_HANDLE h;
239
ACPI_STATUS status;
240
int old_state, error;
241
242
error = 0;
243
if (state < ACPI_STATE_D0 || state > ACPI_STATE_D3)
244
return (EINVAL);
245
246
/*
247
* We set the state using PCI Power Management outside of setting
248
* the ACPI state. This means that when powering down a device, we
249
* first shut it down using PCI, and then using ACPI, which lets ACPI
250
* try to power down any Power Resources that are now no longer used.
251
* When powering up a device, we let ACPI set the state first so that
252
* it can enable any needed Power Resources before changing the PCI
253
* power state.
254
*/
255
ACPI_SERIAL_BEGIN(pci_powerstate);
256
old_state = pci_get_powerstate(child);
257
if (old_state < state && pci_do_power_suspend) {
258
error = pci_set_powerstate_method(dev, child, state);
259
if (error)
260
goto out;
261
}
262
h = acpi_get_handle(child);
263
status = acpi_pwr_switch_consumer(h, state);
264
if (ACPI_SUCCESS(status)) {
265
if (bootverbose)
266
device_printf(dev, "set ACPI power state %s on %s\n",
267
acpi_d_state_to_str(state), acpi_name(h));
268
} else if (status != AE_NOT_FOUND)
269
device_printf(dev,
270
"failed to set ACPI power state %s on %s: %s\n",
271
acpi_d_state_to_str(state), acpi_name(h),
272
AcpiFormatException(status));
273
if (old_state > state && pci_do_power_resume)
274
error = pci_set_powerstate_method(dev, child, state);
275
276
out:
277
ACPI_SERIAL_END(pci_powerstate);
278
return (error);
279
}
280
281
static void
282
acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child)
283
{
284
ACPI_STATUS status;
285
device_t child;
286
287
/*
288
* Occasionally a PCI device may show up as an ACPI device
289
* with a _HID. (For example, the TabletPC TC1000 has a
290
* second PCI-ISA bridge that has a _HID for an
291
* acpi_sysresource device.) In that case, leave ACPI-CA's
292
* device data pointing at the ACPI-enumerated device.
293
*/
294
child = acpi_get_device(handle);
295
if (child != NULL) {
296
KASSERT(device_get_parent(child) ==
297
devclass_get_device(devclass_find("acpi"), 0),
298
("%s: child (%s)'s parent is not acpi0", __func__,
299
acpi_name(handle)));
300
return;
301
}
302
303
/*
304
* Update ACPI-CA to use the PCI enumerated device_t for this handle.
305
*/
306
status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child);
307
if (ACPI_FAILURE(status))
308
printf("WARNING: Unable to attach object data to %s - %s\n",
309
acpi_name(handle), AcpiFormatException(status));
310
}
311
312
static ACPI_STATUS
313
acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, void *context,
314
void **status)
315
{
316
struct acpi_pci_devinfo *dinfo;
317
device_t child;
318
int func, slot;
319
UINT32 address;
320
321
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
322
323
child = context;
324
if (ACPI_FAILURE(acpi_GetInteger(handle, "_ADR", &address)))
325
return_ACPI_STATUS (AE_OK);
326
slot = ACPI_ADR_PCI_SLOT(address);
327
func = ACPI_ADR_PCI_FUNC(address);
328
dinfo = device_get_ivars(child);
329
if (dinfo->ap_dinfo.cfg.func == func &&
330
dinfo->ap_dinfo.cfg.slot == slot) {
331
dinfo->ap_handle = handle;
332
acpi_pci_update_device(handle, child);
333
return_ACPI_STATUS (AE_CTRL_TERMINATE);
334
}
335
return_ACPI_STATUS (AE_OK);
336
}
337
338
void
339
acpi_pci_child_added(device_t dev, device_t child)
340
{
341
342
/*
343
* PCI devices are added via the bus scan in the normal PCI
344
* bus driver. As each device is added, the
345
* acpi_pci_child_added() callback walks the ACPI namespace
346
* under the bridge driver to save ACPI handles to all the
347
* devices that appear in the ACPI namespace as immediate
348
* descendants of the bridge.
349
*
350
* XXX: Sometimes PCI devices show up in the ACPI namespace that
351
* pci_add_children() doesn't find. We currently just ignore
352
* these devices.
353
*/
354
AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
355
acpi_pci_save_handle, NULL, child, NULL);
356
}
357
358
static int
359
acpi_pci_probe(device_t dev)
360
{
361
362
if (acpi_get_handle(dev) == NULL)
363
return (ENXIO);
364
device_set_desc(dev, "ACPI PCI bus");
365
return (BUS_PROBE_DEFAULT);
366
}
367
368
static void
369
acpi_pci_bus_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
370
{
371
device_t dev;
372
373
dev = context;
374
375
switch (notify) {
376
case ACPI_NOTIFY_BUS_CHECK:
377
bus_topo_lock();
378
BUS_RESCAN(dev);
379
bus_topo_unlock();
380
break;
381
default:
382
device_printf(dev, "unknown notify %#x\n", notify);
383
break;
384
}
385
}
386
387
static void
388
acpi_pci_device_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
389
{
390
device_t child, dev;
391
ACPI_STATUS status;
392
int error;
393
394
dev = context;
395
396
switch (notify) {
397
case ACPI_NOTIFY_DEVICE_CHECK:
398
bus_topo_lock();
399
BUS_RESCAN(dev);
400
bus_topo_unlock();
401
break;
402
case ACPI_NOTIFY_EJECT_REQUEST:
403
child = acpi_get_device(h);
404
if (child == NULL) {
405
device_printf(dev, "no device to eject for %s\n",
406
acpi_name(h));
407
return;
408
}
409
bus_topo_lock();
410
error = device_detach(child);
411
if (error) {
412
bus_topo_unlock();
413
device_printf(dev, "failed to detach %s: %d\n",
414
device_get_nameunit(child), error);
415
return;
416
}
417
if ((acpi_quirks & ACPI_Q_CLEAR_PME_ON_DETACH) &&
418
pci_has_pm(child))
419
pci_clear_pme(child);
420
status = acpi_SetInteger(h, "_EJ0", 1);
421
if (ACPI_FAILURE(status)) {
422
bus_topo_unlock();
423
device_printf(dev, "failed to eject %s: %s\n",
424
acpi_name(h), AcpiFormatException(status));
425
return;
426
}
427
if (acpi_quirks & ACPI_Q_DELAY_BEFORE_EJECT_RESCAN)
428
DELAY(10 * 1000);
429
BUS_RESCAN(dev);
430
bus_topo_unlock();
431
break;
432
default:
433
device_printf(dev, "unknown notify %#x for %s\n", notify,
434
acpi_name(h));
435
break;
436
}
437
}
438
439
static ACPI_STATUS
440
acpi_pci_install_device_notify_handler(ACPI_HANDLE handle, UINT32 level,
441
void *context, void **status)
442
{
443
ACPI_HANDLE h;
444
445
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
446
447
if (ACPI_FAILURE(AcpiGetHandle(handle, "_EJ0", &h)))
448
return_ACPI_STATUS (AE_OK);
449
450
AcpiInstallNotifyHandler(handle, ACPI_SYSTEM_NOTIFY,
451
acpi_pci_device_notify_handler, context);
452
return_ACPI_STATUS (AE_OK);
453
}
454
455
static int
456
acpi_pci_attach(device_t dev)
457
{
458
int error;
459
460
error = pci_attach(dev);
461
if (error)
462
return (error);
463
AcpiInstallNotifyHandler(acpi_get_handle(dev), ACPI_SYSTEM_NOTIFY,
464
acpi_pci_bus_notify_handler, dev);
465
AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
466
acpi_pci_install_device_notify_handler, NULL, dev, NULL);
467
468
return (0);
469
}
470
471
static ACPI_STATUS
472
acpi_pci_remove_notify_handler(ACPI_HANDLE handle, UINT32 level, void *context,
473
void **status)
474
{
475
ACPI_HANDLE h;
476
477
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
478
479
if (ACPI_FAILURE(AcpiGetHandle(handle, "_EJ0", &h)))
480
return_ACPI_STATUS (AE_OK);
481
482
AcpiRemoveNotifyHandler(handle, ACPI_SYSTEM_NOTIFY,
483
acpi_pci_device_notify_handler);
484
return_ACPI_STATUS (AE_OK);
485
}
486
487
static int
488
acpi_pci_detach(device_t dev)
489
{
490
491
AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
492
acpi_pci_remove_notify_handler, NULL, dev, NULL);
493
AcpiRemoveNotifyHandler(acpi_get_handle(dev), ACPI_SYSTEM_NOTIFY,
494
acpi_pci_bus_notify_handler);
495
return (pci_detach(dev));
496
}
497
498
#ifdef IOMMU
499
static bus_dma_tag_t
500
acpi_pci_get_dma_tag(device_t bus, device_t child)
501
{
502
bus_dma_tag_t tag;
503
504
if (device_get_parent(child) == bus) {
505
/* try iommu and return if it works */
506
tag = iommu_get_dma_tag(bus, child);
507
} else
508
tag = NULL;
509
if (tag == NULL)
510
tag = pci_get_dma_tag(bus, child);
511
return (tag);
512
}
513
#else
514
static bus_dma_tag_t
515
acpi_pci_get_dma_tag(device_t bus, device_t child)
516
{
517
518
return (pci_get_dma_tag(bus, child));
519
}
520
#endif
521
522