struct device_driver

struct device_driver (defined in include/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, one device_driver represents the body of code that can drive many such devices. It is a statically-allocated structure carrying a name, a pointer to the bus it 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 calling driver_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 bare device_driver: each bus wraps it in a bus-specific structure (struct pci_driver, struct platform_driver) that embeds a device_driver, and convenience macros (module_driver, module_platform_driver) collapse the registration boilerplate to a single line (per driver.rst and 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 with bus, it must be initialised; driver.rst states “The driver must initialize at least the name and bus fields.”

  • bus — a pointer to the bus_type this driver registers on. It tells driver_register() which bus’s klist_drivers to join and whose .match()/.probe() to use. Bus wrappers set this for you (__platform_driver_register does drv->driver.bus = &platform_bus_type).

  • owner — the struct module that owns this driver, almost always set to THIS_MODULE by 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, where owner is NULL; used to build the module-alias links in sysfs.

  • suppress_bind_attrs — a bool that, when true, disables the bind and unbind sysfs files for this driver (bus_add_driver() only calls add_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 — an enum 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 of struct of_device_id terminated by an empty entry, each carrying a Device-Tree compatible string (e.g. { .compatible = "ti,am3359-cpsw" }). This is the match table for Device-Tree-described hardware; the bus’s .match() checks the device’s compatible against it.

  • acpi_match_table — the equivalent array of struct acpi_device_id for 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 returns 0 on success (driver is now bound, dev->driver is set), a negative errno to decline binding (and must release everything it allocated), or -EPROBE_DEFER to 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 in driver.rst.

  • suspend/resume — legacy per-driver PM callbacks; modern drivers use the richer pm field (struct dev_pm_ops) instead.

  • pm — the driver’s power-management operations. When the PM core suspends a device, the bus’s pm ops 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’s coredump sysfs file, asking the driver to dump device state via dev_coredump.

  • p — a pointer to struct driver_private, the driver-core-only bookkeeping (the driver’s kobject, its klist_devices of bound devices, the knode_bus linking it into the bus). Allocated by bus_add_driver(); never touched outside the core.

Uncertain

Verify: that PROBE_PREFER_ASYNCHRONOUS is still the opt-in (rather than default) in 6.12, and the current enum probe_type values. Reason: read from the 6.12 driver.h kerneldoc, 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: check really_probe()/__device_attach async logic and Documentation/ 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;
}
  1. Bus-registered check. The driver’s bus must already have been bus_register()ed; otherwise registration fails -EINVAL with a clear message. This is why driver-init runs after its bus’s init.
  2. Legacy-driver warning. If the driver sets .probe/.remove/.shutdown directly 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 bare device_driver callbacks.
  3. Duplicate-name check. driver_find() walks the bus’s drivers; a name collision fails -EBUSY. Driver names must be unique per bus.
  4. bus_add_driver() — the real work (next section): allocate driver_private, create the sysfs directory, link into the bus’s driver list, and — if autoprobe is on — call driver_attach() to bind against every existing device. 5–6. Attribute groups and uevent. Create the driver’s groups files and emit a KOBJ_ADD uevent so userspace sees the new driver.
  5. 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:

PCIstruct 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;
	...
};

Platformstruct 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 devicebind_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/bind

For 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.remove returns int in 6.12 (the header shows int (*remove)(struct device *dev)) while platform_driver.remove returns void — the long-running .remove return-type conversion was in flight around this era. Reason: the generic device_driver.remove and the platform remove/remove_new union 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_new deprecation 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