acpi_pci.c revision 330938
1/*- 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 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__FBSDID("$FreeBSD: stable/10/sys/dev/acpica/acpi_pci.c 330938 2018-03-14 19:04:40Z jhb $"); 31 32#include "opt_acpi.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/kernel.h> 38#include <sys/malloc.h> 39#include <sys/module.h> 40 41#include <contrib/dev/acpica/include/acpi.h> 42#include <contrib/dev/acpica/include/accommon.h> 43 44#include <dev/acpica/acpivar.h> 45 46#include <sys/pciio.h> 47#include <dev/pci/pcireg.h> 48#include <dev/pci/pcivar.h> 49#include <dev/pci/pci_private.h> 50 51#include "pcib_if.h" 52#include "pci_if.h" 53 54/* Hooks for the ACPI CA debugging infrastructure. */ 55#define _COMPONENT ACPI_BUS 56ACPI_MODULE_NAME("PCI") 57 58struct acpi_pci_devinfo { 59 struct pci_devinfo ap_dinfo; 60 ACPI_HANDLE ap_handle; 61 int ap_flags; 62}; 63 64ACPI_SERIAL_DECL(pci_powerstate, "ACPI PCI power methods"); 65 66/* Be sure that ACPI and PCI power states are equivalent. */ 67CTASSERT(ACPI_STATE_D0 == PCI_POWERSTATE_D0); 68CTASSERT(ACPI_STATE_D1 == PCI_POWERSTATE_D1); 69CTASSERT(ACPI_STATE_D2 == PCI_POWERSTATE_D2); 70CTASSERT(ACPI_STATE_D3 == PCI_POWERSTATE_D3); 71 72static int acpi_pci_attach(device_t dev); 73static void acpi_pci_child_deleted(device_t dev, device_t child); 74static int acpi_pci_child_location_str_method(device_t cbdev, 75 device_t child, char *buf, size_t buflen); 76static int acpi_pci_probe(device_t dev); 77static int acpi_pci_read_ivar(device_t dev, device_t child, int which, 78 uintptr_t *result); 79static int acpi_pci_write_ivar(device_t dev, device_t child, int which, 80 uintptr_t value); 81static ACPI_STATUS acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, 82 void *context, void **status); 83static int acpi_pci_set_powerstate_method(device_t dev, device_t child, 84 int state); 85static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child); 86static bus_dma_tag_t acpi_pci_get_dma_tag(device_t bus, device_t child); 87 88static device_method_t acpi_pci_methods[] = { 89 /* Device interface */ 90 DEVMETHOD(device_probe, acpi_pci_probe), 91 DEVMETHOD(device_attach, acpi_pci_attach), 92 93 /* Bus interface */ 94 DEVMETHOD(bus_read_ivar, acpi_pci_read_ivar), 95 DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar), 96 DEVMETHOD(bus_child_deleted, acpi_pci_child_deleted), 97 DEVMETHOD(bus_child_location_str, acpi_pci_child_location_str_method), 98 DEVMETHOD(bus_get_dma_tag, acpi_pci_get_dma_tag), 99 DEVMETHOD(bus_get_domain, acpi_get_domain), 100 101 /* PCI interface */ 102 DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method), 103 104 DEVMETHOD_END 105}; 106 107static devclass_t pci_devclass; 108 109DEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, sizeof(struct pci_softc), 110 pci_driver); 111DRIVER_MODULE(acpi_pci, pcib, acpi_pci_driver, pci_devclass, 0, 0); 112MODULE_DEPEND(acpi_pci, acpi, 1, 1, 1); 113MODULE_DEPEND(acpi_pci, pci, 1, 1, 1); 114MODULE_VERSION(acpi_pci, 1); 115 116static int 117acpi_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 118{ 119 struct acpi_pci_devinfo *dinfo; 120 121 dinfo = device_get_ivars(child); 122 switch (which) { 123 case ACPI_IVAR_HANDLE: 124 *result = (uintptr_t)dinfo->ap_handle; 125 return (0); 126 case ACPI_IVAR_FLAGS: 127 *result = (uintptr_t)dinfo->ap_flags; 128 return (0); 129 } 130 return (pci_read_ivar(dev, child, which, result)); 131} 132 133static int 134acpi_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 135{ 136 struct acpi_pci_devinfo *dinfo; 137 138 dinfo = device_get_ivars(child); 139 switch (which) { 140 case ACPI_IVAR_HANDLE: 141 dinfo->ap_handle = (ACPI_HANDLE)value; 142 return (0); 143 case ACPI_IVAR_FLAGS: 144 dinfo->ap_flags = (int)value; 145 return (0); 146 } 147 return (pci_write_ivar(dev, child, which, value)); 148} 149 150static void 151acpi_pci_child_deleted(device_t dev, device_t child) 152{ 153 struct acpi_pci_devinfo *dinfo = device_get_ivars(child); 154 155 if (acpi_get_device(dinfo->ap_handle) == child) 156 AcpiDetachData(dinfo->ap_handle, acpi_fake_objhandler); 157 pci_child_deleted(dev, child); 158} 159 160static int 161acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf, 162 size_t buflen) 163{ 164 struct acpi_pci_devinfo *dinfo = device_get_ivars(child); 165 int pxm; 166 char buf2[32]; 167 168 pci_child_location_str_method(cbdev, child, buf, buflen); 169 170 if (dinfo->ap_handle) { 171 strlcat(buf, " handle=", buflen); 172 strlcat(buf, acpi_name(dinfo->ap_handle), buflen); 173 174 if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ap_handle, "_PXM", &pxm))) { 175 snprintf(buf2, 32, " _PXM=%d", pxm); 176 strlcat(buf, buf2, buflen); 177 } 178 } 179 return (0); 180} 181 182/* 183 * PCI power manangement 184 */ 185static int 186acpi_pci_set_powerstate_method(device_t dev, device_t child, int state) 187{ 188 ACPI_HANDLE h; 189 ACPI_STATUS status; 190 int old_state, error; 191 192 error = 0; 193 if (state < ACPI_STATE_D0 || state > ACPI_STATE_D3) 194 return (EINVAL); 195 196 /* 197 * We set the state using PCI Power Management outside of setting 198 * the ACPI state. This means that when powering down a device, we 199 * first shut it down using PCI, and then using ACPI, which lets ACPI 200 * try to power down any Power Resources that are now no longer used. 201 * When powering up a device, we let ACPI set the state first so that 202 * it can enable any needed Power Resources before changing the PCI 203 * power state. 204 */ 205 ACPI_SERIAL_BEGIN(pci_powerstate); 206 old_state = pci_get_powerstate(child); 207 if (old_state < state && pci_do_power_suspend) { 208 error = pci_set_powerstate_method(dev, child, state); 209 if (error) 210 goto out; 211 } 212 h = acpi_get_handle(child); 213 status = acpi_pwr_switch_consumer(h, state); 214 if (ACPI_SUCCESS(status)) { 215 if (bootverbose) 216 device_printf(dev, "set ACPI power state D%d on %s\n", 217 state, acpi_name(h)); 218 } else if (status != AE_NOT_FOUND) 219 device_printf(dev, 220 "failed to set ACPI power state D%d on %s: %s\n", 221 state, acpi_name(h), AcpiFormatException(status)); 222 if (old_state > state && pci_do_power_resume) 223 error = pci_set_powerstate_method(dev, child, state); 224 225out: 226 ACPI_SERIAL_END(pci_powerstate); 227 return (error); 228} 229 230static void 231acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child) 232{ 233 ACPI_STATUS status; 234 device_t child; 235 236 /* 237 * Occasionally a PCI device may show up as an ACPI device 238 * with a _HID. (For example, the TabletPC TC1000 has a 239 * second PCI-ISA bridge that has a _HID for an 240 * acpi_sysresource device.) In that case, leave ACPI-CA's 241 * device data pointing at the ACPI-enumerated device. 242 */ 243 child = acpi_get_device(handle); 244 if (child != NULL) { 245 KASSERT(device_get_parent(child) == 246 devclass_get_device(devclass_find("acpi"), 0), 247 ("%s: child (%s)'s parent is not acpi0", __func__, 248 acpi_name(handle))); 249 return; 250 } 251 252 /* 253 * Update ACPI-CA to use the PCI enumerated device_t for this handle. 254 */ 255 status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child); 256 if (ACPI_FAILURE(status)) 257 printf("WARNING: Unable to attach object data to %s - %s\n", 258 acpi_name(handle), AcpiFormatException(status)); 259} 260 261static ACPI_STATUS 262acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, void *context, 263 void **status) 264{ 265 struct acpi_pci_devinfo *dinfo; 266 device_t *devlist; 267 int devcount, i, func, slot; 268 UINT32 address; 269 270 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 271 272 if (ACPI_FAILURE(acpi_GetInteger(handle, "_ADR", &address))) 273 return_ACPI_STATUS (AE_OK); 274 slot = ACPI_ADR_PCI_SLOT(address); 275 func = ACPI_ADR_PCI_FUNC(address); 276 if (device_get_children((device_t)context, &devlist, &devcount) != 0) 277 return_ACPI_STATUS (AE_OK); 278 for (i = 0; i < devcount; i++) { 279 dinfo = device_get_ivars(devlist[i]); 280 if (dinfo->ap_dinfo.cfg.func == func && 281 dinfo->ap_dinfo.cfg.slot == slot) { 282 dinfo->ap_handle = handle; 283 acpi_pci_update_device(handle, devlist[i]); 284 break; 285 } 286 } 287 free(devlist, M_TEMP); 288 return_ACPI_STATUS (AE_OK); 289} 290 291static int 292acpi_pci_probe(device_t dev) 293{ 294 295 if (acpi_get_handle(dev) == NULL) 296 return (ENXIO); 297 device_set_desc(dev, "ACPI PCI bus"); 298 return (0); 299} 300 301static int 302acpi_pci_attach(device_t dev) 303{ 304 int busno, domain, error; 305 306 error = pci_attach_common(dev); 307 if (error) 308 return (error); 309 310 /* 311 * Since there can be multiple independantly numbered PCI 312 * busses on systems with multiple PCI domains, we can't use 313 * the unit number to decide which bus we are probing. We ask 314 * the parent pcib what our domain and bus numbers are. 315 */ 316 domain = pcib_get_domain(dev); 317 busno = pcib_get_bus(dev); 318 319 /* 320 * First, PCI devices are added as in the normal PCI bus driver. 321 * Afterwards, the ACPI namespace under the bridge driver is 322 * walked to save ACPI handles to all the devices that appear in 323 * the ACPI namespace as immediate descendants of the bridge. 324 * 325 * XXX: Sometimes PCI devices show up in the ACPI namespace that 326 * pci_add_children() doesn't find. We currently just ignore 327 * these devices. 328 */ 329 pci_add_children(dev, domain, busno, sizeof(struct acpi_pci_devinfo)); 330 AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1, 331 acpi_pci_save_handle, NULL, dev, NULL); 332 333 return (bus_generic_attach(dev)); 334} 335 336#ifdef ACPI_DMAR 337bus_dma_tag_t dmar_get_dma_tag(device_t dev, device_t child); 338static bus_dma_tag_t 339acpi_pci_get_dma_tag(device_t bus, device_t child) 340{ 341 bus_dma_tag_t tag; 342 343 if (device_get_parent(child) == bus) { 344 /* try dmar and return if it works */ 345 tag = dmar_get_dma_tag(bus, child); 346 } else 347 tag = NULL; 348 if (tag == NULL) 349 tag = pci_get_dma_tag(bus, child); 350 return (tag); 351} 352#else 353static bus_dma_tag_t 354acpi_pci_get_dma_tag(device_t bus, device_t child) 355{ 356 357 return (pci_get_dma_tag(bus, child)); 358} 359#endif 360