static int acpi_pci_bind(struct acpi_device *device) { ACPI_STATUS status; ACPI_HANDLE handle; struct pci_bus *bus; struct pci_dev *dev; dev = acpi_get_pci_dev(device->handle); if (!dev) return 0; device->pci_dev = dev; dev->acpi_dev = device; dbgprintf("bind ACPI %s PCI_%x_%x\n", device->pnp.bus_id, dev->vendor, dev->device); // pci_acpi_add_pm_notifier(device, dev); // if (device->wakeup.flags.run_wake) // device_set_run_wake(&dev->dev, true); /* * Install the 'bind' function to facilitate callbacks for * children of the P2P bridge. */ if (dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d is a PCI bridge\n", pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; } /* * Evaluate and parse _PRT, if exists. This code allows parsing of * _PRT objects within the scope of non-bridge devices. Note that * _PRTs within the scope of a PCI bridge assume the bridge's * subordinate bus number. * * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? */ status = AcpiGetHandle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_FAILURE(status)) goto out; if (dev->subordinate) bus = dev->subordinate; else bus = dev->bus; acpi_pci_irq_add_prt(device->handle, bus); out: // pci_dev_put(dev); return 0; }
static int acpi_pci_bind(struct acpi_device *device) { acpi_status status; acpi_handle handle; unsigned char bus; struct pci_dev *dev; dev = acpi_get_pci_dev(device->handle); if (!dev) return 0; pci_acpi_add_pm_notifier(device, dev); acpi_power_resource_register_device(&dev->dev, device->handle); if (device->wakeup.flags.run_wake) device_set_run_wake(&dev->dev, true); /* * Install the 'bind' function to facilitate callbacks for * children of the P2P bridge. */ if (dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d is a PCI bridge\n", pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; } /* * Evaluate and parse _PRT, if exists. This code allows parsing of * _PRT objects within the scope of non-bridge devices. Note that * _PRTs within the scope of a PCI bridge assume the bridge's * subordinate bus number. * * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_FAILURE(status)) goto out; if (dev->subordinate) bus = dev->subordinate->number; else bus = dev->bus->number; acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); out: pci_dev_put(dev); return 0; }
int acpi_pci_bind(struct acpi_device *device) { int result = 0; acpi_status status; struct acpi_pci_data *data; struct acpi_pci_data *pdata; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle; if (!device || !device->parent) return -EINVAL; data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); if (!data) return -ENOMEM; status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); if (ACPI_FAILURE(status)) { kfree(data); return -ENODEV; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", (char *)buffer.pointer)); /* * Segment & Bus * ------------- * These are obtained via the parent device's ACPI-PCI context. */ status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, (void **)&pdata); if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { ACPI_EXCEPTION((AE_INFO, status, "Invalid ACPI-PCI context for parent device %s", acpi_device_bid(device->parent))); result = -ENODEV; goto end; } data->id.segment = pdata->id.segment; data->id.bus = pdata->bus->number; /* * Device & Function * ----------------- * These are simply obtained from the device's _ADR method. Note * that a value of zero is valid. */ data->id.device = device->pnp.bus_address >> 16; data->id.function = device->pnp.bus_address & 0xFFFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); /* * TBD: Support slot devices (e.g. function=0xFFFF). */ /* * Locate PCI Device * ----------------- * Locate matching device in PCI namespace. If it doesn't exist * this typically means that the device isn't currently inserted * (e.g. docking station, port replicator, etc.). */ data->dev = pci_get_slot(pdata->bus, PCI_DEVFN(data->id.device, data->id.function)); if (!data->dev) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d not present in PCI namespace\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; goto end; } if (!data->dev->bus) { printk(KERN_ERR PREFIX "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", data->id.segment, data->id.bus, data->id.device, data->id.function); result = -ENODEV; goto end; } /* * PCI Bridge? * ----------- * If so, set the 'bus' field and install the 'bind' function to * facilitate callbacks for all of its children. */ if (data->dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d is a PCI bridge\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); data->bus = data->dev->subordinate; device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; } /* * Attach ACPI-PCI Context * ----------------------- * Thus binding the ACPI and PCI devices. */ status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to attach ACPI-PCI context to device %s", acpi_device_bid(device))); result = -ENODEV; goto end; } /* * PCI Routing Table * ----------------- * Evaluate and parse _PRT, if exists. This code is independent of * PCI bridges (above) to allow parsing of _PRT objects within the * scope of non-bridge devices. Note that _PRTs within the scope of * a PCI bridge assume the bridge's subordinate bus number. * * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) { if (data->bus) /* PCI-PCI bridge */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->bus->number); else /* non-bridge PCI device */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->id.bus); } end: kfree(buffer.pointer); if (result) { pci_dev_put(data->dev); kfree(data); } return result; }