75cff725d9
struct bus_type should never be modified in a sysfs callback as there is nothing in the structure to modify, and frankly, the structure is almost never used in a sysfs callback, so mark it as constant to allow struct bus_type to be moved to read-only memory. Cc: "David S. Miller" <davem@davemloft.net> Cc: "James E.J. Bottomley" <jejb@linux.ibm.com> Cc: "K. Y. Srinivasan" <kys@microsoft.com> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Alexandre Bounine <alex.bou9@gmail.com> Cc: Alison Schofield <alison.schofield@intel.com> Cc: Ben Widawsky <bwidawsk@kernel.org> Cc: Dexuan Cui <decui@microsoft.com> Cc: Eric Dumazet <edumazet@google.com> Cc: Haiyang Zhang <haiyangz@microsoft.com> Cc: Hannes Reinecke <hare@suse.de> Cc: Harald Freudenberger <freude@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Hu Haowen <src.res@email.cn> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Laurentiu Tudor <laurentiu.tudor@nxp.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Stuart Yoder <stuyoder@gmail.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Vishal Verma <vishal.l.verma@intel.com> Cc: Yanteng Si <siyanteng@loongson.cn> Acked-by: Ilya Dryomov <idryomov@gmail.com> # rbd Acked-by: Ira Weiny <ira.weiny@intel.com> # cxl Reviewed-by: Alex Shi <alexs@kernel.org> Acked-by: Iwona Winiarska <iwona.winiarska@intel.com> Acked-by: Dan Williams <dan.j.williams@intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> # pci Acked-by: Wei Liu <wei.liu@kernel.org> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> # scsi Link: https://lore.kernel.org/r/20230313182918.1312597-23-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
147 lines
4.0 KiB
ReStructuredText
147 lines
4.0 KiB
ReStructuredText
=========
|
|
Bus Types
|
|
=========
|
|
|
|
Definition
|
|
~~~~~~~~~~
|
|
See the kerneldoc for the struct bus_type.
|
|
|
|
int bus_register(struct bus_type * bus);
|
|
|
|
|
|
Declaration
|
|
~~~~~~~~~~~
|
|
|
|
Each bus type in the kernel (PCI, USB, etc) should declare one static
|
|
object of this type. They must initialize the name field, and may
|
|
optionally initialize the match callback::
|
|
|
|
struct bus_type pci_bus_type = {
|
|
.name = "pci",
|
|
.match = pci_bus_match,
|
|
};
|
|
|
|
The structure should be exported to drivers in a header file:
|
|
|
|
extern struct bus_type pci_bus_type;
|
|
|
|
|
|
Registration
|
|
~~~~~~~~~~~~
|
|
|
|
When a bus driver is initialized, it calls bus_register. This
|
|
initializes the rest of the fields in the bus object and inserts it
|
|
into a global list of bus types. Once the bus object is registered,
|
|
the fields in it are usable by the bus driver.
|
|
|
|
|
|
Callbacks
|
|
~~~~~~~~~
|
|
|
|
match(): Attaching Drivers to Devices
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The format of device ID structures and the semantics for comparing
|
|
them are inherently bus-specific. Drivers typically declare an array
|
|
of device IDs of devices they support that reside in a bus-specific
|
|
driver structure.
|
|
|
|
The purpose of the match callback is to give the bus an opportunity to
|
|
determine if a particular driver supports a particular device by
|
|
comparing the device IDs the driver supports with the device ID of a
|
|
particular device, without sacrificing bus-specific functionality or
|
|
type-safety.
|
|
|
|
When a driver is registered with the bus, the bus's list of devices is
|
|
iterated over, and the match callback is called for each device that
|
|
does not have a driver associated with it.
|
|
|
|
|
|
|
|
Device and Driver Lists
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The lists of devices and drivers are intended to replace the local
|
|
lists that many buses keep. They are lists of struct devices and
|
|
struct device_drivers, respectively. Bus drivers are free to use the
|
|
lists as they please, but conversion to the bus-specific type may be
|
|
necessary.
|
|
|
|
The LDM core provides helper functions for iterating over each list::
|
|
|
|
int bus_for_each_dev(struct bus_type * bus, struct device * start,
|
|
void * data,
|
|
int (*fn)(struct device *, void *));
|
|
|
|
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
|
|
void * data, int (*fn)(struct device_driver *, void *));
|
|
|
|
These helpers iterate over the respective list, and call the callback
|
|
for each device or driver in the list. All list accesses are
|
|
synchronized by taking the bus's lock (read currently). The reference
|
|
count on each object in the list is incremented before the callback is
|
|
called; it is decremented after the next object has been obtained. The
|
|
lock is not held when calling the callback.
|
|
|
|
|
|
sysfs
|
|
~~~~~~~~
|
|
There is a top-level directory named 'bus'.
|
|
|
|
Each bus gets a directory in the bus directory, along with two default
|
|
directories::
|
|
|
|
/sys/bus/pci/
|
|
|-- devices
|
|
`-- drivers
|
|
|
|
Drivers registered with the bus get a directory in the bus's drivers
|
|
directory::
|
|
|
|
/sys/bus/pci/
|
|
|-- devices
|
|
`-- drivers
|
|
|-- Intel ICH
|
|
|-- Intel ICH Joystick
|
|
|-- agpgart
|
|
`-- e100
|
|
|
|
Each device that is discovered on a bus of that type gets a symlink in
|
|
the bus's devices directory to the device's directory in the physical
|
|
hierarchy::
|
|
|
|
/sys/bus/pci/
|
|
|-- devices
|
|
| |-- 00:00.0 -> ../../../root/pci0/00:00.0
|
|
| |-- 00:01.0 -> ../../../root/pci0/00:01.0
|
|
| `-- 00:02.0 -> ../../../root/pci0/00:02.0
|
|
`-- drivers
|
|
|
|
|
|
Exporting Attributes
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
::
|
|
|
|
struct bus_attribute {
|
|
struct attribute attr;
|
|
ssize_t (*show)(const struct bus_type *, char * buf);
|
|
ssize_t (*store)(const struct bus_type *, const char * buf, size_t count);
|
|
};
|
|
|
|
Bus drivers can export attributes using the BUS_ATTR_RW macro that works
|
|
similarly to the DEVICE_ATTR_RW macro for devices. For example, a
|
|
definition like this::
|
|
|
|
static BUS_ATTR_RW(debug);
|
|
|
|
is equivalent to declaring::
|
|
|
|
static bus_attribute bus_attr_debug;
|
|
|
|
This can then be used to add and remove the attribute from the bus's
|
|
sysfs directory using::
|
|
|
|
int bus_create_file(struct bus_type *, struct bus_attribute *);
|
|
void bus_remove_file(struct bus_type *, struct bus_attribute *);
|