Esempio n. 1
0
int
acpi_pci_bind_root (
    struct acpi_device	*device,
    struct acpi_pci_id	*id,
    struct pci_bus		*bus)
{
    int			result = 0;
    acpi_status		status = AE_OK;
    struct acpi_pci_data	*data = NULL;
    char			*pathname = NULL;
    struct acpi_buffer	buffer = {0, NULL};

    ACPI_FUNCTION_TRACE("acpi_pci_bind_root");

    pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
    if(!pathname)
        return_VALUE(-ENOMEM);
    memset(pathname, 0, ACPI_PATHNAME_MAX);

    buffer.length = ACPI_PATHNAME_MAX;
    buffer.pointer = pathname;

    if (!device || !id || !bus) {
        kfree(pathname);
        return_VALUE(-EINVAL);
    }

    data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
    if (!data) {
        kfree(pathname);
        return_VALUE(-ENOMEM);
    }
    memset(data, 0, sizeof(struct acpi_pci_data));

    data->id = *id;
    data->bus = bus;
    device->ops.bind = acpi_pci_bind;
    device->ops.unbind = acpi_pci_unbind;

    acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);

    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
                      "%02x:%02x\n", pathname, id->segment, id->bus));

    status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
    if (ACPI_FAILURE(status)) {
        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                          "Unable to attach ACPI-PCI context to device %s\n",
                          pathname));
        result = -ENODEV;
        goto end;
    }

end:
    kfree(pathname);
    if (result != 0)
        kfree(data);

    return_VALUE(result);
}
Esempio n. 2
0
static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
{
	int trips = 0;
	int result;
	acpi_status status;
	int i;

	if (tz->trips.critical.flags.valid)
		trips++;

	if (tz->trips.hot.flags.valid)
		trips++;

	if (tz->trips.passive.flags.valid)
		trips++;

	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
			tz->trips.active[i].flags.valid; i++, trips++);

	if (tz->trips.passive.flags.valid)
		tz->thermal_zone =
			thermal_zone_device_register("acpitz", trips, 0, tz,
						&acpi_thermal_zone_ops, NULL,
						     tz->trips.passive.tsp*100,
						     tz->polling_frequency*100);
	else
		tz->thermal_zone =
			thermal_zone_device_register("acpitz", trips, 0, tz,
						&acpi_thermal_zone_ops, NULL,
						0, tz->polling_frequency*100);
	if (IS_ERR(tz->thermal_zone))
		return -ENODEV;

	result = sysfs_create_link(&tz->device->dev.kobj,
				   &tz->thermal_zone->device.kobj, "thermal_zone");
	if (result)
		return result;

	result = sysfs_create_link(&tz->thermal_zone->device.kobj,
				   &tz->device->dev.kobj, "device");
	if (result)
		return result;

	status = acpi_attach_data(tz->device->handle,
				  acpi_bus_private_data_handler,
				  tz->thermal_zone);
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR PREFIX
				"Error attaching device data\n");
		return -ENODEV;
	}

	tz->tz_enabled = 1;

	dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
		 tz->thermal_zone->id);
	return 0;
}
Esempio n. 3
0
int acpi_bus_attach_private_data(acpi_handle handle, void *data)
{
	acpi_status status;

	status = acpi_attach_data(handle,
			acpi_bus_private_data_handler, data);
	if (ACPI_FAILURE(status)) {
		acpi_handle_debug(handle, "Error attaching device data\n");
		return -ENODEV;
	}

	return 0;
}
int
acpi_pci_bind_root(struct acpi_device *device,
		   struct acpi_pci_id *id, struct pci_bus *bus)
{
	int result = 0;
	acpi_status status;
	struct acpi_pci_data *data = NULL;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

	if (!device || !id || !bus) {
		return -EINVAL;
	}

	data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->id = *id;
	data->bus = bus;
	device->ops.bind = acpi_pci_bind;
	device->ops.unbind = acpi_pci_unbind;

	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 root bridge [%s] to "
			"%04x:%02x\n", (char *)buffer.pointer,
			id->segment, id->bus));

	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",
				(char *)buffer.pointer));
		result = -ENODEV;
		goto end;
	}

      end:
	kfree(buffer.pointer);
	if (result != 0)
		kfree(data);

	return result;
}
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;
}
Esempio n. 6
0
/**
 * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
 * @chip:      gpio chip
 *
 * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
 * handled by ACPI event methods which need to be called from the GPIO
 * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which
 * gpio pins have acpi event methods and assigns interrupt handlers that calls
 * the acpi event methods for those pins.
 */
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
    struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
    struct acpi_resource *res;
    acpi_handle handle, evt_handle;
    struct list_head *evt_pins = NULL;
    acpi_status status;
    unsigned int pin;
    int irq, ret;
    char ev_name[5];

    if (!chip->dev || !chip->to_irq)
        return;

    handle = ACPI_HANDLE(chip->dev);
    if (!handle)
        return;

    status = acpi_get_event_resources(handle, &buf);
    if (ACPI_FAILURE(status))
        return;

    status = acpi_get_handle(handle, "_EVT", &evt_handle);
    if (ACPI_SUCCESS(status)) {
        evt_pins = kzalloc(sizeof(*evt_pins), GFP_KERNEL);
        if (evt_pins) {
            INIT_LIST_HEAD(evt_pins);
            status = acpi_attach_data(handle, acpi_gpio_evt_dh,
                                      evt_pins);
            if (ACPI_FAILURE(status)) {
                kfree(evt_pins);
                evt_pins = NULL;
            }
        }
    }

    /*
     * If a GPIO interrupt has an ACPI event handler method, or _EVT is
     * present, set up an interrupt handler that calls the ACPI event
     * handler.
     */
    for (res = buf.pointer;
            res && (res->type != ACPI_RESOURCE_TYPE_END_TAG);
            res = ACPI_NEXT_RESOURCE(res)) {
        irq_handler_t handler = NULL;
        void *data;

        if (res->type != ACPI_RESOURCE_TYPE_GPIO ||
                res->data.gpio.connection_type !=
                ACPI_RESOURCE_GPIO_TYPE_INT)
            continue;

        pin = res->data.gpio.pin_table[0];
        if (pin > chip->ngpio)
            continue;

        irq = chip->to_irq(chip, pin);
        if (irq < 0)
            continue;

        if (pin <= 255) {
            acpi_handle ev_handle;

            sprintf(ev_name, "_%c%02X",
                    res->data.gpio.triggering ? 'E' : 'L', pin);
            status = acpi_get_handle(handle, ev_name, &ev_handle);
            if (ACPI_SUCCESS(status)) {
                handler = acpi_gpio_irq_handler;
                data = ev_handle;
            }
        }
        if (!handler && evt_pins) {
            struct acpi_gpio_evt_pin *evt_pin;

            evt_pin = kzalloc(sizeof(*evt_pin), GFP_KERNEL);
            if (!evt_pin)
                continue;

            list_add_tail(&evt_pin->node, evt_pins);
            evt_pin->evt_handle = evt_handle;
            evt_pin->pin = pin;
            evt_pin->irq = irq;
            handler = acpi_gpio_irq_handler_evt;
            data = evt_pin;
        }
        if (!handler)
            continue;

        /* Assume BIOS sets the triggering, so no flags */
        ret = devm_request_threaded_irq(chip->dev, irq, NULL, handler,
                                        0, "GPIO-signaled-ACPI-event",
                                        data);
        if (ret)
            dev_err(chip->dev,
                    "Failed to request IRQ %d ACPI event handler\n",
                    irq);
    }
}