예제 #1
0
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;
}
예제 #2
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;
}