2002-06-04 16:30:27

by Patrick Mochel

[permalink] [raw]
Subject: device model documentation 3/3


Docuemnt 3: binding.txt


Driver Binding

Driver binding is the process of associating a device with a device
driver that can control it. Bus drivers have typically handled this
because there have been bus-specific structures to represent the
devices and the drivers. With generic device and device driver
structures, most of the binding can take place using generic common
code.


The bus type structure contains a list of all devices that on that bus
type in the system. When device_register is called for a device, it is
inserted into the end of this list. The bus object also contains a
list of all drivers of that bus type. When driver_register is called
for a driver, it is inserted into the end of this list.

There are two events which trigger driver binding: when a new device
is added and when a new driver is added. When a new device is added,
the bus's list of drivers is iterated over to find one that supports
it. In order to determine that, the device ID of the device must match
one of the device IDs that the driver supports. The format and
semantics for comparing IDs is bus-specific. Instead of trying to
derive a complex state machine and matching algorithm, it is up to the
bus driver to provide a callback to compare a device against the IDs
of a driver. The bus returns 1 if a match was found; 0 otherwise.

int bind(struct device * dev, struct device_driver * drv);

If a match is found, the device's driver field is set to the driver
and the driver's probe callback is called. This gives the driver a
chance to verify that it really does support the hardware, and that
it's in a working state.

The device is inserted into the driver's list of devices it supports. A
symlink is created in the driver's directory for the device that points to
its physical location. (Not implemented yet)


The process is almost identical for when a new driver is added.
The bus's list of devices is iterated over to find a match. Devices
that already have a driver are skipped. All the devices are iterated
over, to bind as many devices as possible to the driver.


When a device is removed, the reference count for it will eventually
go to 0. When it does, the remove callback of the driver is called. It
is removed from the driver's list of devices and the reference count
of the driver is decremented. All symlinks between the two are removed.

When a driver is removed, the list of devices that it supports is
iterated over, and the driver's remove callback is called for each
one. The device is removed from that list and the symlinks removed.




2002-06-05 12:24:21

by Arnd Bergmann

[permalink] [raw]
Subject: Re: device model documentation 3/3

On Tue Jun 04 2002 - 11:25:19 EST,
Patrick Mochel <[email protected]> wrote:

> When a driver is removed, the list of devices that it supports is
> iterated over, and the driver's remove callback is called for each
> one. The device is removed from that list and the symlinks removed.

Maybe I'm blind, but I can't see how this works without races for
bridge device drivers. Imagine for example what happens when I rmmod
a usb hcd driver. Its module use count should be zero as long as the
devices attached to it are not in use, right?
When I e.g. open a file in directory of a device behind my hcd, the
devices use count is incremented but can still remove the driver.
Reading the file after module unload then can do bad things if the
show() callback was inside the hcd driver.
Did I miss the obvious anywhere?

Arnd <><

2002-06-05 17:54:37

by Greg KH

[permalink] [raw]
Subject: Re: device model documentation 3/3

On Wed, Jun 05, 2002 at 04:24:18PM +0200, Arnd Bergmann wrote:
> On Tue Jun 04 2002 - 11:25:19 EST,
> Patrick Mochel <[email protected]> wrote:
>
> > When a driver is removed, the list of devices that it supports is
> > iterated over, and the driver's remove callback is called for each
> > one. The device is removed from that list and the symlinks removed.
>
> Maybe I'm blind, but I can't see how this works without races for
> bridge device drivers. Imagine for example what happens when I rmmod
> a usb hcd driver. Its module use count should be zero as long as the
> devices attached to it are not in use, right?

A USB HCD driver module use count is always zero, so you can always
unload it. Now if this is a good idea or not is debatable :)

thanks,

greg k-h

2002-06-05 19:00:35

by Patrick Mochel

[permalink] [raw]
Subject: Re: device model documentation 3/3


On Wed, 5 Jun 2002, Arnd Bergmann wrote:

> On Tue Jun 04 2002 - 11:25:19 EST,
> Patrick Mochel <[email protected]> wrote:
>
> > When a driver is removed, the list of devices that it supports is
> > iterated over, and the driver's remove callback is called for each
> > one. The device is removed from that list and the symlinks removed.
>
> Maybe I'm blind, but I can't see how this works without races for
> bridge device drivers. Imagine for example what happens when I rmmod
> a usb hcd driver. Its module use count should be zero as long as the
> devices attached to it are not in use, right?
> When I e.g. open a file in directory of a device behind my hcd, the
> devices use count is incremented but can still remove the driver.
> Reading the file after module unload then can do bad things if the
> show() callback was inside the hcd driver.
> Did I miss the obvious anywhere?

No, that's a race that would affect all modular drivers. Ideally, we would
want to pin the module in memory on file open, then decrement the usage
count on close. We could do this by adding a struct module field to struct
driver_file_entry...

-pat

2002-06-06 11:19:11

by Arnd Bergmann

[permalink] [raw]
Subject: Re: device model documentation 3/3

On Wednesday 05 June 2002 20:56, Patrick Mochel wrote:

> No, that's a race that would affect all modular drivers. Ideally, we would
> want to pin the module in memory on file open, then decrement the usage
> count on close. We could do this by adding a struct module field to struct
> driver_file_entry...

Hmm, adding anything to driver_file_entry will make it take twice
as much memory (it's 8 * sizeof(void*) now, allocated with kmalloc),
so I wouldn't want to have that if there is another way.

Adding an owner field to struct device is probably not enough if bridge
devices should be able to add files to their children. You would need
at least two struct module pointers then. Also, it requires every device
driver to initialize the owner field (at least one for its struct
device_driver).

An alternative might be a rw_semaphore in struct device that protects
the store and show callbacks in its files. On module unload, rmmod would
just have to wait on the semaphore if it is held by any readers.
Of course that protects only against the race between module unload
and file open, but there can be others of anyone does get_device without
incrementing the use counts for the right modules.

Arnd <><