Re: [PATCH v2 3/3 UPDATED] i2c / ACPI: add ACPI enumeration support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Nov 17, 2012 at 2:55 AM, Mika Westerberg
<mika.westerberg@xxxxxxxxxxxxxxx> wrote:
> On Sat, Nov 17, 2012 at 10:03:54AM +0200, Mika Westerberg wrote:
>> On Fri, Nov 16, 2012 at 11:46:40PM -0700, Bjorn Helgaas wrote:
>> > On Fri, Nov 16, 2012 at 10:28 AM, Mika Westerberg
>> > <mika.westerberg@xxxxxxxxxxxxxxx> wrote:
>> > > ...
>> > > From: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
>> > > Date: Mon, 10 Sep 2012 12:12:32 +0300
>> > > Subject: [PATCH] i2c / ACPI: add ACPI enumeration support
>> > >
>> > > ACPI 5 introduced I2cSerialBus resource that makes it possible to enumerate
>> > > and configure the I2C slave devices behind the I2C controller. This patch
>> > > adds helper functions to support I2C slave enumeration.
>> > >
>> > > An ACPI enabled I2C controller driver only needs to call acpi_i2c_register_devices()
>> > > in order to get its slave devices enumerated, created and bound to the
>> > > corresponding ACPI handle.
>> >
>> > I must admit I don't understand the strategy here.  Likely it's only
>> > because I haven't been paying enough attention, but I'll ask anyway in
>> > case anybody else is similarly confused.
>> >
>> > The callchain when we enumerate these slave devices looks like this:
>> >
>> >     acpi_i2c_register_devices(struct i2c_adapter *)
>> >       acpi_walk_namespace(adapter->dev.acpi_handle, acpi_i2c_add_device)
>> >         acpi_i2c_add_device
>> >           acpi_bus_get_device
>> >           acpi_bus_get_status
>> >           acpi_dev_get_resources(..., acpi_i2c_add_resource, ...)
>> >           <find IRQ, addr>
>> >           acpi_dev_free_resources
>> >           i2c_new_device
>> >             client = kzalloc
>> >             client->dev = ...
>> >             device_register(&client->dev)
>> >
>> > Is the ACPI namespace in question something like the following?
>> >
>> >     Device {                    # i2C master, i.e., the i2c_adapter
>> >       _HID PNPmmmm
>> >       Device {                  # I2C slave 1, i.e.,  a client
>> >         _HID PNPsss1
>> >         _CRS
>> >           SerialBus/I2C addr addr1, mode mode1
>> >           IRQ irq1
>> >       }
>> >       Device {                  # I2C slave 2
>> >         _HID PNPsss2
>> >         _CRS
>> >           SerialBus/I2C addr addr2, mode mode2
>> >           IRQ irq2
>> >       }
>> >     }
>>
>> Yes.
>>
>> > _CRS is a device configuration method, so I would expect that it
>> > exists within the scope of a Device() object.  The way I'm used to
>> > this working is for a driver to specify "I know about PNPsss1
>> > devices."
>>
>> Yes.
>>
>> > But it looks like acpi_i2c_register() walks the namespace below an i2c
>> > master device, registering a new i2c device (a slave) for every ACPI
>> > device node with a _CRS method that contains a SERIAL_BUS/TYPE_I2C
>> > descriptor.  It seems like you're basically claiming those devices
>> > nodes based on the contents of their _CRS, not based on their PNP IDs,
>> > which seems strange to me.
>>
>> Yes, if we only matched the PNP IDs we would get bunch of PNP devices which
>> certainly doesn't help us to reuse the existing I2C drivers. So instead of
>> creating a new glue driver for ACPI or PNP device we added this enumeration
>> method that then creates the I2C devices, just like DT does.
>
> In other words, what this whole thing is trying to achieve is something
> along the lines of:
>
>         - Instead of making PNP or ACPI devices out of every device in the
>           ACPI namespace we use the resources returned by the _CRS
>           method for a given device as a hint of what type of device it is.
>
>         - If we find I2CSerialBus() we assume it is an I2C device and
>           create i2c_device (and i2c_client) and register this to the I2C
>           core.
>
>         - If we find SPISerialBus() we assume it is a SPI device and create
>           corresponding spidevice and register it to the SPI core.
>
>         - Devices that don't have a bus are represented as platform devices
>           (based on the table in drivers/acpi/scan.c). The reason for this
>           is that most of the SoC devices have already platform driver so
>           we can easily reuse the existing drivers.

Using _CRS contents to infer the device type feels like a mistake to
me.  It doesn't generalize to arbitrary devices.  I don't think it's
the intent of the spec, which seems clearly to be "start with the
_HID/_CID to identify devices," so it violates the principle of least
surprise.

I'm not sure it's even safe to rely on _CRS being useful until after
the OS runs _SRS.  Sec 6.2 of the spec (ACPI 5.0) says the OS uses
_PRS to determine what resources the device needs and _SRS to assign
them, and it *may* use _CRS to learn any current assignments (I know
this doesn't match current Linux behavior very well).  I interpret
that to mean the device may be disabled and return nothing in _CRS
until after the OS evaluates _SRS to enable the device.

I think it will make it harder to reason about and refactor ACPI
because it's "unusual."  For example, the acpi_i2c_register_devices ->
acpi_i2c_add_device path allocates a new struct device (in struct
i2c_client) and registers it.  Now we have a struct device in struct
acpi_device, in struct pnp_dev, *and* in struct i2c_client, and all
refer to the same thing.  What does that mean?  The sysfs picture
seems confusing to me.

I assume you mean the acpi_platform_device_ids[] table you added with
91e56878058.  Having a table of IDs that are treated specially by the
core is a bit of a concern for me because it means we need to add
things to it every time a new platform device comes along.  The patch
didn't include clear criteria for deciding what qualifies.  For
example, I don't know whether PCI host bridges would qualify as
platform devices.  I guess maybe they would, because they don't have a
bus (though of course they have acpi_bus_type like all other ACPI
devices)?

> The implementation follows the Device Tree as much as possible so that
> adding support for DT and ACPI to a driver would be similar and thus easy
> for people who know either method.
>
> An alternative would be to create PNP or ACPI glue drivers for each device
> that then create the corresponding real device like platform or I2C which
> means that we need add much more lines of unnecessary code to the kernel
> compared to adding the ACPI/PNP IDs to the driver which takes only few
> lines of code.
>
> We still allow more complex configuration with the means of
> dev->acpi_handle. So for example if driver needs to call _DSM in order to
> retrieve some parameters for the device it can do so with the help of
> dev->acpi_handle.

I think the benefit here is that you can merely point
.acpi_match_table at an acpi_device_id[] table, then use
platform_get_resource() as a generic way to get resources, whether the
platform device came from OF, ACPI, etc.  The alternative would be to
add, e.g., a PNP driver with a .probe() method that uses
pnp_get_resource().  That's not very much code, but it is more, even
if the .probe() method just calls a device registration function
that's shared across bus types.

That benefit seems like a great thing, and my question then is why
wouldn't we just do it across the board and make platform devices for
*all* ACPI devices without having the I2C and SPI special cases?

Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux