DRIVER INSTANCE OVERVIEW(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… driver instance overview πŸ’…

straight from the Kernel API Manual, section 9 β€” pull up a chair bestie


✨ DESCRIPTION ✨

okay so first things first: a device instance for a drm driver? that's a struct drm_device. that's the whole vibe. 🫢

you allocate and initialize it with devm_drm_dev_alloc, and like, usually you do that from the bus-specific ->probe callbacks that your driver implements. iykyk.

then the driver has to initialize all the various subsystems for the drm device β€” we're talking memory management, vblank handling, modesetting support and initial output configuration, plus obviously initializing all the corresponding hardware bits. all of it. no skipping. πŸ™ˆ

and finally, when everything is up and running and ready for userspace, the device instance can be published using drm_dev_register. that's the moment. main character energy. πŸ‘‘

πŸ’€ the deprecated way (yes it still exists, don't @ me): there's also deprecated support for initializing device instances using bus-specific helpers and the drm_driver.load callback. but because of backwards-compatibility needs, the device instance has to be published too early, which requires unpretty global locking to make safe β€” so it's therefore only supported for existing drivers that are not yet converted to the new scheme. not for you, new friend. 🚫

πŸŽ€ cleanup time (do it backwards, bestie)

when cleaning up a device instance, everything needs to be done in reverse:

  1. First, unpublish the device instance with drm_dev_unregister.
  2. Then clean up any other resources allocated at device initialization, and drop the driver's reference to drm_device using drm_dev_put.
🌸 important note, like genuinely important: any allocation or resource which is visible to userspace must be released only when the final drm_dev_put is called, and not when the driver is unbound from the underlying physical struct device. best to use drm_device managed resources with drmm_add_action, drmm_kmalloc and related functions. slay. ✨

also, devres managed resources like devm_kmalloc can only be used for resources directly related to the underlying hardware device, and only used in code paths fully protected by drm_dev_enter and drm_dev_exit. that's the rule, no cap. πŸ’…


πŸ¦‹ Display driver example πŸ¦‹

the following example shows a typical structure of a DRM display driver. it's focused on the probe function and the other functions that are almost always present, and it serves as a demonstration of devm_drm_dev_alloc. 🧚

struct driver_device {
        struct drm_device drm;
        void *userspace_facing;
        struct clk *pclk;
};

static const struct drm_driver driver_drm_driver = {
        [...]
};

static int driver_probe(struct platform_device *pdev)
{
        struct driver_device *priv;
        struct drm_device *drm;
        int ret;

        priv = devm_drm_dev_alloc(pdev->dev, driver_drm_driver,
                                  struct driver_device, drm);
        if (IS_ERR(priv))
                return PTR_ERR(priv);
        drm = priv->drm;

        ret = drmm_mode_config_init(drm);
        if (ret)
                return ret;

        priv->userspace_facing = drmm_kzalloc(..., GFP_KERNEL);
        if (!priv->userspace_facing)
                return -ENOMEM;

        priv->pclk = devm_clk_get(dev, "PCLK");
        if (IS_ERR(priv->pclk))
                return PTR_ERR(priv->pclk);

        // Further setup, display pipeline etc

        platform_set_drvdata(pdev, drm);

        ret = drm_mode_config_create_initial_state(drm);
        if (ret)
                return ret;

        ret = drm_dev_register(drm);
        if (ret)
                return ret;

        drm_fbdev_{...}_setup(drm, 32);

        return 0;
}

// This function is called before the devm_ resources are released
static int driver_remove(struct platform_device *pdev)
{
        struct drm_device *drm = platform_get_drvdata(pdev);

        drm_dev_unregister(drm);
        drm_atomic_helper_shutdown(drm)

        return 0;
}

// This function is called on kernel restart and shutdown
static void driver_shutdown(struct platform_device *pdev)
{
        drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
}

static int __maybe_unused driver_pm_suspend(struct device *dev)
{
        return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
}

static int __maybe_unused driver_pm_resume(struct device *dev)
{
        drm_mode_config_helper_resume(dev_get_drvdata(dev));

        return 0;
}

static const struct dev_pm_ops driver_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(driver_pm_suspend, driver_pm_resume)
};

static struct platform_driver driver_driver = {
        .driver = {
                [...]
                .pm = driver_pm_ops,
        },
        .probe = driver_probe,
        .remove = driver_remove,
        .shutdown = driver_shutdown,
};
module_platform_driver(driver_driver);

πŸ”Œ unplugging, for the USB / DT overlay girlies

drivers that want to support device unplugging (USB, DT overlay unload) should use drm_dev_unplug instead of drm_dev_unregister. the driver must protect regions that are accessing device resources to prevent use after they're released. this is done using drm_dev_enter and drm_dev_exit. πŸ›‘οΈ

😭 there is one shortcoming however: drm_dev_unplug marks the drm_device as unplugged before drm_atomic_helper_shutdown is called. this means that if the disable code paths are protected, they will not run on regular driver module unload, possibly leaving the hardware enabled. yeah. that's the whole thing. bestie. πŸ’€

🌈 SEE ALSO 🌈


πŸŽ€ that's the whole page, bestie β€” you ate. go forth and probe responsibly. πŸ’œ

this has been ./drivers/gpu/drm, October 2026, driver instance overview(9) β€” mwah 🫢✨

πŸ“¦ where this page comes from