| 1 | =========
|
| 2 | Bus Types
|
| 3 | =========
|
| 4 |
|
| 5 | Definition
|
| 6 | ~~~~~~~~~~
|
| 7 | See the kerneldoc for the struct bus_type.
|
| 8 |
|
| 9 | int bus_register(struct bus_type * bus);
|
| 10 |
|
| 11 |
|
| 12 | Declaration
|
| 13 | ~~~~~~~~~~~
|
| 14 |
|
| 15 | Each bus type in the kernel (PCI, USB, etc) should declare one static
|
| 16 | object of this type. They must initialize the name field, and may
|
| 17 | optionally initialize the match callback::
|
| 18 |
|
| 19 | struct bus_type pci_bus_type = {
|
| 20 | .name = "pci",
|
| 21 | .match = pci_bus_match,
|
| 22 | };
|
| 23 |
|
| 24 | The structure should be exported to drivers in a header file:
|
| 25 |
|
| 26 | extern struct bus_type pci_bus_type;
|
| 27 |
|
| 28 |
|
| 29 | Registration
|
| 30 | ~~~~~~~~~~~~
|
| 31 |
|
| 32 | When a bus driver is initialized, it calls bus_register. This
|
| 33 | initializes the rest of the fields in the bus object and inserts it
|
| 34 | into a global list of bus types. Once the bus object is registered,
|
| 35 | the fields in it are usable by the bus driver.
|
| 36 |
|
| 37 |
|
| 38 | Callbacks
|
| 39 | ~~~~~~~~~
|
| 40 |
|
| 41 | match(): Attaching Drivers to Devices
|
| 42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 43 |
|
| 44 | The format of device ID structures and the semantics for comparing
|
| 45 | them are inherently bus-specific. Drivers typically declare an array
|
| 46 | of device IDs of devices they support that reside in a bus-specific
|
| 47 | driver structure.
|
| 48 |
|
| 49 | The purpose of the match callback is to give the bus an opportunity to
|
| 50 | determine if a particular driver supports a particular device by
|
| 51 | comparing the device IDs the driver supports with the device ID of a
|
| 52 | particular device, without sacrificing bus-specific functionality or
|
| 53 | type-safety.
|
| 54 |
|
| 55 | When a driver is registered with the bus, the bus's list of devices is
|
| 56 | iterated over, and the match callback is called for each device that
|
| 57 | does not have a driver associated with it.
|
| 58 |
|
| 59 |
|
| 60 |
|
| 61 | Device and Driver Lists
|
| 62 | ~~~~~~~~~~~~~~~~~~~~~~~
|
| 63 |
|
| 64 | The lists of devices and drivers are intended to replace the local
|
| 65 | lists that many buses keep. They are lists of struct devices and
|
| 66 | struct device_drivers, respectively. Bus drivers are free to use the
|
| 67 | lists as they please, but conversion to the bus-specific type may be
|
| 68 | necessary.
|
| 69 |
|
| 70 | The LDM core provides helper functions for iterating over each list::
|
| 71 |
|
| 72 | int bus_for_each_dev(struct bus_type * bus, struct device * start,
|
| 73 | void * data,
|
| 74 | int (*fn)(struct device *, void *));
|
| 75 |
|
| 76 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
|
| 77 | void * data, int (*fn)(struct device_driver *, void *));
|
| 78 |
|
| 79 | These helpers iterate over the respective list, and call the callback
|
| 80 | for each device or driver in the list. All list accesses are
|
| 81 | synchronized by taking the bus's lock (read currently). The reference
|
| 82 | count on each object in the list is incremented before the callback is
|
| 83 | called; it is decremented after the next object has been obtained. The
|
| 84 | lock is not held when calling the callback.
|
| 85 |
|
| 86 |
|
| 87 | sysfs
|
| 88 | ~~~~~~~~
|
| 89 | There is a top-level directory named 'bus'.
|
| 90 |
|
| 91 | Each bus gets a directory in the bus directory, along with two default
|
| 92 | directories::
|
| 93 |
|
| 94 | /sys/bus/pci/
|
| 95 | |-- devices
|
| 96 | `-- drivers
|
| 97 |
|
| 98 | Drivers registered with the bus get a directory in the bus's drivers
|
| 99 | directory::
|
| 100 |
|
| 101 | /sys/bus/pci/
|
| 102 | |-- devices
|
| 103 | `-- drivers
|
| 104 | |-- Intel ICH
|
| 105 | |-- Intel ICH Joystick
|
| 106 | |-- agpgart
|
| 107 | `-- e100
|
| 108 |
|
| 109 | Each device that is discovered on a bus of that type gets a symlink in
|
| 110 | the bus's devices directory to the device's directory in the physical
|
| 111 | hierarchy::
|
| 112 |
|
| 113 | /sys/bus/pci/
|
| 114 | |-- devices
|
| 115 | | |-- 00:00.0 -> ../../../root/pci0/00:00.0
|
| 116 | | |-- 00:01.0 -> ../../../root/pci0/00:01.0
|
| 117 | | `-- 00:02.0 -> ../../../root/pci0/00:02.0
|
| 118 | `-- drivers
|
| 119 |
|
| 120 |
|
| 121 | Exporting Attributes
|
| 122 | ~~~~~~~~~~~~~~~~~~~~
|
| 123 |
|
| 124 | ::
|
| 125 |
|
| 126 | struct bus_attribute {
|
| 127 | struct attribute attr;
|
| 128 | ssize_t (*show)(const struct bus_type *, char * buf);
|
| 129 | ssize_t (*store)(const struct bus_type *, const char * buf, size_t count);
|
| 130 | };
|
| 131 |
|
| 132 | Bus drivers can export attributes using the BUS_ATTR_RW macro that works
|
| 133 | similarly to the DEVICE_ATTR_RW macro for devices. For example, a
|
| 134 | definition like this::
|
| 135 |
|
| 136 | static BUS_ATTR_RW(debug);
|
| 137 |
|
| 138 | is equivalent to declaring::
|
| 139 |
|
| 140 | static bus_attribute bus_attr_debug;
|
| 141 |
|
| 142 | This can then be used to add and remove the attribute from the bus's
|
| 143 | sysfs directory using::
|
| 144 |
|
| 145 | int bus_create_file(struct bus_type *, struct bus_attribute *);
|
| 146 | void bus_remove_file(struct bus_type *, struct bus_attribute *);
|