Re: [RFC PATCH] platform: Faciliatate the creation of pseduo-platform busses

From: Grant Likely
Date: Thu Aug 05 2010 - 19:00:23 EST


On Tue, Aug 3, 2010 at 6:17 PM, Patrick Pannuto <ppannuto@xxxxxxxxxxx> wrote:
>>>>>
>>>>>    struct platform_device sub_bus1 = {
>>>>>            .name           = "sub_bus1",
>>>>>            .id             = -1,
>>>>>            .dev.bus        = &my_bus_type,
>>>>>    }
>>>>>    EXPORT_SYMBOL_GPL(sub_bus1);
>>>>
>>>> You really want a bus hanging off of a bus?  Normally you need a device
>>>> to do that, which is what I think you have here, but the naming is a bit
>>>> odd to me.
>>>>
>>>> What would you do with this "sub bus"?  It's just a device, but you are
>>>> wanting it to be around for something.
>>>>
>>>
>>> It's for power management stuff, basically, there are actual physical buses
>>> involved that can be completely powered off IFF all of their devices are
>>> not in use. Plus it actually matches bus topology this way.
>>
>> Then create a real bus hanging off of a device, not another device that
>> "acts" like a bus here, right?  Or am I missing the point?
>>
>
> The motivation for doing it this was is that one driver could drive
> devices on two different subbusses.  In the example, "my-driver" could
> drive a device on sub_bus1 AND sub_bus2 (if there were 2+ devices, one
> or more on each bus).
>
> From my understanding, this is not possible if they are actually
> different busses.

It sounds an awful lot like 2 separate concepts are being conflated
here. In Linux terminology, we have two things:

/bus types/ describe the common behavour of similarly attached things.
/physical or logical busses/ are where devices are actually attached
registered to the system.

These are not the same thing.

The primary thing that a bus-type provides is the set of device driver
that can be bound to the device plus some common functionality.
Almost every struct device has the 'struct bus_type bus' field set so
that it can be bound against a device driver when it is registered.

Every struct device also has a 'struct device *parent' field. The
parent field denotes where the device lives in the Linux device model
(see /sys/devices/*), but it says *nothing* about what the bus type of
device it is. Remember I mentioned physical/logical busses earlier?
Well the core Linux device model doesn't really have a concept of bus
instances, it only knows about devices and bus types. The .parent
field is the closest thing the device model has to a bus instance, but
the model places no constraints on the bus type of each child 'struct
device'.

(caveat: many bus_types do have a concept of bus instances; but that
is specific to the bus_type. The core device model doesn't care.
Also, in practical terms, yes most sibling devices will also be of the
same bus_type, but it is not a given, and it is not enforced.)

For example, a system can have many physical pci busses, but all the
devices hanging off those busses are still just registered on
pci_bus_type. The parent of those devices, however, reflects the
physical bus the device is attached to.

In fact, the bus type has absolutely no bearing on where a device
actually lives in the Linux driver model. A common misunderstanding
is that all platform devices live under /sys/devices/platform.

This also is not true.

By default the platform bus will put devices without a parent into
/sys/devices/platform, but if parent is set, then the device will be
registered where the parent pointer tells it to be registered. It is
totally okay to have the following structure (off the top of my head):

system_bus (platform_bus_type, registers a bunch of child devices)
|--pci_bus (platform_bus_type; implements a pci host bridge)
| |--usb host controller 1 (pci_bus_type, implements a usb bus instance)
| |--usb host controller 2 (pci_bus_type, implements a usb bus instance)
| |--fpga (pci_bus_type, implements a bunch of devices)
| |--spi controller (platform_bus_type)
| |--custom peripheral (platform_bus_type)
|--uart (platform_bus_type)
|--uart (platform_bus_type)
|--ethernet (platform_bus_type)
|--external bus (platform_bus_type; represents and external local bus)
| |--i2c controller (platform_bus_type)
| | |--eeprom (i2c_bus_type)
| | |--temperature sensor (i2c_bus_type)
|--gpio controller (platform_bus_type)

Platform devices can show up just about anywhere in the tree.

(On that point Greg, what is the reason for even having the
/sys/devices/platform/ parent? Why not just let the platform devices
sit at the root of the device tree? In the OF case (granted, I'm
biased) all of the platform_device registrations reflect the actual
device hierarchy expressed in the device tree data.)

So, the *only* reason to have a different bus_type is if the actual
behaviour of the bus is different. A different bus type wouldn't even
cause a different topology if doing so wouldn't make sense. For
example in the OMAP case, the topology might look like:

system_bus (platform_bus_type, registers a bunch of child devices)
| ...
|--uart (omap_bus_type)
|--uart (omap_bus_type)
|--ethernet (platform_bus_type)

See? Devices of different types can often be siblings at the same
device layer. (note: not *always* true. PCI busses for instance
always expect to only host pci_devices and visa-versa, but for simple
platform-like busses it may be true).

Now, having gone on this whole long tirade, it looks like having
separate platform bus types may not be the best approach after all.
Magnus and Kevin are exploring using devres to handle implementing the
system-specific behaviour. It is certainly an area for more research
and experimental implementations.

g.

--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/