linux-device-driver

What is the possible use of dev_set_drvdata and dev_get_drvdata


I just want to know what is the possible use case when we have to use these set and get driver APIs. All I get to know that the data is saved, and at a later time we can use data to do something. My question is when we really need to do that?

     /*
      * These exports can't be _GPL due to .h files using this within them, and it
      * might break something that was previously working...
     */
     void *dev_get_drvdata(const struct device *dev)
     {
          if (dev && dev->p)
                  return dev->p->driver_data;
          return NULL;
     }
     EXPORT_SYMBOL(dev_get_drvdata);

     void dev_set_drvdata(struct device *dev, void *data)
     {
        int error;
 
        if (!dev)
                 return;
        if (!dev->p) {
                 error = device_private_init(dev);
                 if (error)
                         return;
        }
        dev->p->driver_data = data;
     }
     EXPORT_SYMBOL(dev_set_drvdata);

Solution

  • The driver core handles different stages of running the driver. You may consider a driver code as a set of callbacks, such as ->probe(), ->remove(), and so on. For details you can check struct platform_driver or struct pci_driver definition.

    So, how can you communicate between the callbacks?

    Right, you have at least two ways:

    Thus, we have a pointer to a private member which can be used as a container of useful information that should be passed through callbacks.

    Why we need that? Most of the drivers request some resources and save pointers to them somewhere at probe stage. To avoid a leak of the resources you have to free them at the remove stage. That's how it used.

    As pointed out by allsey87, another useful pattern is to pass a current state of the device across callbacks. One of the real example is power management callbacks (->suspend(), ->resume(), etc).

    Interestingly the author of the Linux Misc Device: general protection fault at misc_deregister() on driver with private data allocation question tried to use driver data of the miscelleneous device (which is available via the this_device member of struct miscdevice). However, as we may see, the misc device framework uses that field for its own needs and user must not intervene that. The correct approach in such cases is to embed the struct miscdevice into your custom structure and use container_of() approach (remembering that Linux kernel is written in OOP paradigm). Example: https://elixir.bootlin.com/linux/v6.5-rc3/source/lib/test_kmod.c#L121 (definition), https://elixir.bootlin.com/linux/v6.5-rc3/source/lib/test_kmod.c#L153 (getter).