struct device_driver
struct device_driver(defined ininclude/linux/device/driver.h) is the driver model’s representation of a driver as a whole — the code that knows how to operate a class of hardware, distinct from any single device instance. Where struct device represents one piece of hardware, onedevice_driverrepresents the body of code that can drive many such devices. It is a statically-allocated structure carrying aname, a pointer to thebusit lives on, a small table of callbacks (probe,remove,shutdown,pm), and the match tables (of_match_table,acpi_match_table) that tell the bus which devices it can claim. A driver enters the model by callingdriver_register(), which links it onto its bus and triggers the match-and-bind walk against every already-discovered device. In practice almost no one fills in a baredevice_driver: each bus wraps it in a bus-specific structure (struct pci_driver,struct platform_driver) that embeds adevice_driver, and convenience macros (module_driver,module_platform_driver) collapse the registration boilerplate to a single line (perdriver.rstand the 6.12 source, verified 2026-06-20).
This note owns the driver object: its fields, driver_register/driver_unregister, how bus-specific wrappers embed it, the module_driver family of macros, and manual binding through /sys/bus/*/drivers/*/bind and unbind. The bus the driver registers onto — including the two lists and .match() — is struct bus_type and Bus Registration; the actual match→probe machinery is Driver Binding and the Probe Flow and Device-Driver Matching. This note explains the object and its registration, not the bind internals.
Mental Model
A device_driver is a job application pinned to a bus’s notice board. The application states the applicant’s name (name), which board it is posted to (bus), and — crucially — the criteria of jobs it will accept (of_match_table, acpi_match_table, or a bus-specific ID table). When you post the application (driver_register()), the bus’s clerk immediately scans every open position currently on the board (every unbound device) and, for each one the criteria match, calls the applicant in for the job (.probe()). The application also stays pinned: any future device that matches will likewise be handed to this driver. The driver object is the durable, instance-independent record; individual devices come and go and bind against it.
flowchart TB subgraph WRAP["Bus-specific wrapper (e.g. struct platform_driver)"] PROBE["probe(struct platform_device *)"] IDT["id_table / of_match_table"] DD["struct device_driver driver;<br/>(embedded)"] end WRAP -->|"module_platform_driver(...)<br/>→ platform_driver_register()"| REG REG["__platform_driver_register():<br/>drv->driver.bus = &platform_bus_type<br/>drv->driver.owner = THIS_MODULE"] -->|"driver_register(&drv->driver)"| CORE CORE["driver_register():<br/>1. bus_is_registered?<br/>2. driver_find() dup check<br/>3. bus_add_driver()"] -->|"links into klist_drivers<br/>creates /sys/bus/.../drivers/<name>/"| BUS["struct bus_type"] CORE -->|"if drivers_autoprobe"| ATTACH["driver_attach():<br/>walk every device,<br/>bus->match() then bus->probe()"] ATTACH -->|"on match"| PR[".probe(dev) →<br/>dev->driver set, bound"]
From source declaration to bound driver. What it shows: a driver author writes a bus-specific wrapper that embeds a device_driver; a one-line macro expands to the bus’s register function, which fills in .bus and .owner and calls the generic driver_register(); that links the driver onto the bus and (if autoprobe is on) immediately walks every device trying to bind. The insight: the embedded device_driver is the only part the generic core understands — the wrapper and macros exist purely to give type-safe, boilerplate-free access to it.
The struct device_driver Fields
The Linux 6.12 definition from include/linux/device/driver.h:
struct device_driver {
const char *name;
const struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
enum probe_type probe_type;
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
int (*probe) (struct device *dev);
void (*sync_state)(struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct attribute_group **dev_groups;
const struct dev_pm_ops *pm;
void (*coredump) (struct device *dev);
struct driver_private *p;
};The load-bearing fields:
-
name— the driver’s name, used for the dedup check, for the/sys/bus/<bus>/drivers/<name>/directory, and as a last-resort match key on buses (like platform) that fall back to name comparison. Together withbus, it must be initialised;driver.rststates “The driver must initialize at least the name and bus fields.” -
bus— a pointer to the bus_type this driver registers on. It tellsdriver_register()which bus’sklist_driversto join and whose.match()/.probe()to use. Bus wrappers set this for you (__platform_driver_registerdoesdrv->driver.bus = &platform_bus_type). -
owner— thestruct modulethat owns this driver, almost always set toTHIS_MODULEby the registration macro. It lets the core take a reference on the module while the driver is bound, so the module cannot be unloaded out from under a live device. -
mod_name— the module name for built-in (statically-linked) drivers, whereownerisNULL; used to build the module-alias links in sysfs. -
suppress_bind_attrs— aboolthat, whentrue, disables thebindandunbindsysfs files for this driver (bus_add_driver()only callsadd_bind_files()when!drv->suppress_bind_attrs). Drivers set this when manual unbinding is unsafe (e.g. a driver for hardware that cannot be torn down at runtime without crashing the system). -
probe_type— anenum probe_type(PROBE_DEFAULT_STRATEGY,PROBE_PREFER_ASYNCHRONOUS,PROBE_FORCE_SYNCHRONOUS) that hints whether the driver’s probe may run asynchronously. Slow-probing drivers opt into async to speed boot; drivers whose probe order matters force synchronous. The kerneldoc notes “the end goal is to switch the kernel to use asynchronous probing by default.” -
of_match_table— an array ofstruct of_device_idterminated by an empty entry, each carrying a Device-Treecompatiblestring (e.g.{ .compatible = "ti,am3359-cpsw" }). This is the match table for Device-Tree-described hardware; the bus’s.match()checks the device’scompatibleagainst it. -
acpi_match_table— the equivalent array ofstruct acpi_device_idfor ACPI-described hardware (matching on the ACPI Hardware ID, “HID”). A driver supporting both firmware schemes carries both tables. -
probe(dev)— the callback that claims and initialises a device. It is called (via the bus’s generic probe wrapper) once the bus has matched a device to this driver. It returns0on success (driver is now bound,dev->driveris set), a negative errno to decline binding (and must release everything it allocated), or-EPROBE_DEFERto ask to be retried later because a dependency is not ready. The bus calls the bus’s.probe(), which forwards to this — see Driver Binding and the Probe Flow. -
remove(dev)— the inverse of probe: unbind from the device, freeing per-device resources. Called on hot-removal, module unload, manual unbind, or reboot. -
shutdown(dev)— quiesce the device at system shutdown. -
sync_state(dev)— called once, after all consumers of the device have probed, for clean handoff of bootloader-configured hardware (regulators, clocks, IOMMUs). Detailed indriver.rst. -
suspend/resume— legacy per-driver PM callbacks; modern drivers use the richerpmfield (struct dev_pm_ops) instead. -
pm— the driver’s power-management operations. When the PM core suspends a device, the bus’spmops typically forward to this. Hook into Runtime Power Management in Drivers. -
groups— sysfs attribute groups auto-created in the driver’s own/sys/bus/<bus>/drivers/<name>/directory;dev_groups— attribute groups auto-attached to each device instance once it binds to this driver. These give leak-free per-driver and per-bound-device sysfs files. -
coredump(dev)— invoked when userspace writes the driver’scoredumpsysfs file, asking the driver to dump device state viadev_coredump. -
p— a pointer tostruct driver_private, the driver-core-only bookkeeping (the driver’s kobject, itsklist_devicesof bound devices, theknode_buslinking it into the bus). Allocated bybus_add_driver(); never touched outside the core.
Uncertain
Verify: that
PROBE_PREFER_ASYNCHRONOUSis still the opt-in (rather than default) in 6.12, and the currentenum probe_typevalues. Reason: read from the 6.12driver.hkerneldoc, which says async-by-default is the goal, not yet the default — but whether any subsystem flipped its default by 6.12 was not separately checked. To resolve: checkreally_probe()/__device_attachasync logic andDocumentation/at the v6.12 tag. uncertain
driver_register() — What Registration Does
The generic entry point is driver_register() in drivers/base/driver.c. Its 6.12 body:
int driver_register(struct device_driver *drv)
{
struct device_driver *other;
if (!bus_is_registered(drv->bus)) { /* 1 */
pr_err("Driver '%s' was unable to register with bus_type '%s' "
"because the bus was not initialized.\n",
drv->name, drv->bus->name);
return -EINVAL;
}
if ((drv->bus->probe && drv->probe) || /* 2 */
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
pr_warn("Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus); /* 3 */
if (other) {
pr_err("Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv); /* 4 */
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups); /* 5 */
...
kobject_uevent(&drv->p->kobj, KOBJ_ADD); /* 6 */
deferred_probe_extend_timeout(); /* 7 */
return ret;
}- Bus-registered check. The driver’s
busmust already have beenbus_register()ed; otherwise registration fails-EINVALwith a clear message. This is why driver-init runs after its bus’s init. - Legacy-driver warning. If the driver sets
.probe/.remove/.shutdowndirectly and the bus also defines them, the core warns “Driver needs updating — please use bus_type methods.” Modern drivers route through the bus wrapper, not the baredevice_drivercallbacks. - Duplicate-name check.
driver_find()walks the bus’s drivers; a name collision fails-EBUSY. Driver names must be unique per bus. bus_add_driver()— the real work (next section): allocatedriver_private, create the sysfs directory, link into the bus’s driver list, and — if autoprobe is on — calldriver_attach()to bind against every existing device. 5–6. Attribute groups and uevent. Create the driver’sgroupsfiles and emit aKOBJ_ADDuevent so userspace sees the new driver.deferred_probe_extend_timeout()— nudges the deferred-probe timeout, since a newly-registered driver may be the missing supplier some deferred device was waiting on (Deferred Probing and EPROBE_DEFER).
bus_add_driver() (in bus.c) is where the driver actually joins the bus: it kzallocs the driver_private, sets drv->p = priv, parents the driver’s kobject under the bus’s drivers_kset (creating /sys/bus/<bus>/drivers/<name>/), links it into klist_drivers, and — the key line — if (sp->drivers_autoprobe) driver_attach(drv);. driver_attach() then walks every device on the bus and tries to bind. So registration and binding-against-existing-devices happen in one call.
driver_unregister() is the inverse: driver_remove_groups() then bus_remove_driver(), which removes the bind files, detaches the driver from every device it controls (driver_detach()), drops the module links, and unregisters the kobject.
Bus-Specific Wrappers Embed device_driver
A bare device_driver is rarely written, because the match criteria are bus-specific and demand bus-specific types for type-safety. The solution, stated in driver.rst, is that “Bus-specific drivers should include a generic struct device_driver in the definition of the bus-specific driver.” Two real examples from 6.12:
PCI — struct pci_driver (from include/linux/pci.h):
struct pci_driver {
const char *name;
const struct pci_device_id *id_table; /* the match table */
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
void (*remove)(struct pci_dev *dev);
...
struct device_driver driver; /* embedded */
struct pci_dynids dynids;
...
};Platform — struct platform_driver (from include/linux/platform_device.h):
struct platform_driver {
int (*probe)(struct platform_device *);
union {
void (*remove)(struct platform_device *);
void (*remove_new)(struct platform_device *);
};
void (*shutdown)(struct platform_device *);
...
struct device_driver driver; /* embedded */
const struct platform_device_id *id_table;
...
};Two things make this work. First, the bus-specific probe takes a bus-specific type (struct pci_dev *, struct platform_device *), which is type-safe; the generic device_driver.probe takes a plain struct device *, so the bus’s generic probe wrapper (platform_probe, set as platform_bus_type.probe) uses container_of() / to_platform_device() to recover the bus-specific type before forwarding to the driver’s bus-specific probe. Second, container_of() recovers the wrapper from the embedded member: to_platform_driver(drv) is container_of(drv, struct platform_driver, driver), and to_pci_driver(drv) likewise. The embedded device_driver is the handle the generic core holds; the wrapper is what the driver author fills in.
The registration wrapper wires the two together. __platform_driver_register() is tiny:
int __platform_driver_register(struct platform_driver *drv, struct module *owner)
{
drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
return driver_register(&drv->driver);
}It fills in the embedded device_driver’s owner and bus, then calls the generic driver_register(). pci_register_driver() / __pci_register_driver() do the analogous thing with pci_bus_type. The author never sets .driver.bus by hand.
The module_driver / module_platform_driver Convenience Macros
Most drivers do nothing in module init/exit except register and unregister. The module_driver() macro (from driver.h) collapses that to one line by generating the module_init/module_exit functions:
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);This is a builder macro — the kerneldoc says “do not use it on its own”; each bus wraps it. The platform bus’s wrapper (from platform_device.h):
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)So a complete platform driver’s registration is one line:
static struct platform_driver foo_driver = {
.probe = foo_probe,
.remove = foo_remove,
.driver = {
.name = "foo",
.of_match_table = foo_of_match,
},
};
module_platform_driver(foo_driver);That single macro expands to foo_driver_init() (calling platform_driver_register(&foo_driver) → driver_register()) wired to module_init, and foo_driver_exit() (calling platform_driver_unregister) wired to module_exit. The parallel builtin_driver() / builtin_platform_driver() macros do the same for statically-linked drivers but use device_initcall() instead of module_init and omit the exit path (built-in code is never unloaded). PCI’s equivalent is module_pci_driver(__pci_driver). The macros are why a modern driver’s bottom line is so terse — all the registration plumbing is generated.
Manual Binding: /sys/bus/*/drivers/*/{bind,unbind}
When suppress_bind_attrs is false, bus_add_driver() creates two write-only files in the driver’s sysfs directory: bind and unbind. Writing a device name to them manually attaches or detaches the driver — independent of automatic matching. This is invaluable for debugging, for driver hot-swapping, and for handing a device to VFIO/userspace. From drivers/base/bus.c:
static ssize_t unbind_store(struct device_driver *drv, const char *buf, size_t count)
{
struct device *dev = bus_find_device_by_name(drv->bus, NULL, buf);
int err = -ENODEV;
if (dev && dev->driver == drv) {
device_driver_detach(dev); /* tear down the binding */
err = count;
}
put_device(dev);
return err;
}
static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t count)
{
struct device *dev = bus_find_device_by_name(drv->bus, NULL, buf);
int err = -ENODEV;
if (dev && driver_match_device(drv, dev)) { /* still must match! */
err = device_driver_attach(drv, dev);
if (!err)
err = count;
}
put_device(dev);
return err;
}The critical subtlety, flagged in the source comment: manual bind still requires the driver to want the device — bind_store calls driver_match_device(drv, dev) (the bus’s .match()) before attaching. You cannot use bind to force a driver onto hardware its match table rejects; the file only lets you bind a device the driver would have matched anyway (e.g. one it skipped because autoprobe was off, or that you previously unbound). unbind, by contrast, only checks dev->driver == drv. A typical session:
# Detach the nvme driver from a specific NVMe device:
echo 0000:01:00.0 > /sys/bus/pci/drivers/nvme/unbind
# Re-attach it later:
echo 0000:01:00.0 > /sys/bus/pci/drivers/nvme/bindFor VFIO passthrough you unbind from the native driver and bind to vfio-pci. Note these files only exist when the driver did not set suppress_bind_attrs — drivers for hardware that cannot survive a runtime teardown deliberately hide them.
Failure Modes and Common Misunderstandings
“echo dev > .../bind returns -ENODEV but the device exists.” Either the name doesn’t match an entry in the bus’s devices/ (wrong format — PCI wants 0000:01:00.0, not 01:00.0), or driver_match_device() rejected it because the driver’s match table doesn’t cover that device. bind is not an override.
“There is no bind/unbind file.” The driver set suppress_bind_attrs = true. This is intentional; it cannot be toggled from userspace.
“Driver registered but probe never ran.” Registration links the driver onto the bus but binding only happens if drivers_autoprobe is on and a device matches. Check /sys/bus/<bus>/drivers_autoprobe, the device’s presence under devices/, the match table, and whether probe deferred (Deferred Probing and EPROBE_DEFER).
“driver_register() returned -EINVAL.” The bus wasn’t registered yet — a link-order / initcall-order problem. The driver’s subsystem init must run after the bus’s.
Confusing the wrapper’s .probe with the embedded .driver.probe. A platform driver sets platform_driver.probe (takes struct platform_device *), not device_driver.probe. Setting the latter directly trips the “needs updating” warning and bypasses the type-safe wrapper.
-EBUSY on register. Two drivers on the same bus share a name. Names must be unique per bus.
Uncertain
Verify: that
device_driver.removereturnsintin 6.12 (the header showsint (*remove)(struct device *dev)) whileplatform_driver.removereturnsvoid— the long-running.removereturn-type conversion was in flight around this era. Reason: the genericdevice_driver.removeand the platformremove/remove_newunion were read from 6.12 headers, but the exact state of the tree-wide conversion at 6.12 was not fully traced. To resolve: check the.remove/.remove_newdeprecation timeline in the v6.12..v6.18 changelogs. uncertain
Production Notes
The dominant modern pattern is: a bus-specific wrapper (platform_driver, pci_driver, i2c_driver, spi_driver) embedding a device_driver, a match table (of_match_table for Device Tree, acpi_match_table for ACPI, or a bus ID table for PCI/USB), devm_*-managed resource acquisition in .probe() so error paths and .remove() shrink to nothing (Managed Device Resources devres), and a single module_*_driver() line at the bottom. This is why a clean driver’s skeleton is so short — the model generates registration, manages sysfs files via groups/dev_groups, and auto-releases resources on unbind.
suppress_bind_attrs matters in production hardening: exposing unbind on critical hardware (the boot disk controller, the IOMMU) is a foot-gun, so such drivers suppress it. The bind/unbind files are also the mechanism behind device hot-swap testing and the standard VFIO-passthrough workflow used by virtualization (driver-override + unbind from native + bind to vfio-pci).
The owner = THIS_MODULE wiring is what makes module reference-counting correct: while any device is bound, the core holds a reference on the owning module, so rmmod blocks until all devices unbind. Forgetting owner (only possible if you bypass the registration macros) breaks this and lets a module unload while still driving live hardware.
See Also
- struct bus_type and Bus Registration — the bus this driver registers onto;
driver_register()callsbus_add_driver()which links into the bus’sklist_drivers - struct device — the device object a driver binds to; the driver’s
klist_devicestracks every device it controls - Driver Binding and the Probe Flow — the
really_probe()machinery that runs the driver’s.probe() - Device-Driver Matching — how
of_match_table/acpi_match_table/ ID tables decide a match - Platform Devices and Drivers —
struct platform_driverandmodule_platform_driverin depth - Deferred Probing and EPROBE_DEFER — what a
.probe()returning-EPROBE_DEFERtriggers - Module Parameters and Metadata Macros — the
MODULE_*macros that accompany a driver - Loadable Kernel Modules — how the
.kocarrying the driver is loaded and howownerties to it - Linux Device Drivers and Device Model MOC — parent map (§2, Buses, Drivers, and the Probe/Bind Flow)