Summary: is the platform_data
field of struct device
free to use in a device driver module?
I am creating a very simple sysfs entry for my character device driver module to allow me to control an internal variable (because I know using ioctl()
and the proc
filesystem are deprecated.) I call class_create()
to make a class in /sys/class/
and then device_create()
to make a new device entry. Then I call device_create_file()
to set up my load and store routines for the driver. I want to lock my driver in these routines. I have a mutex in my driver's main structure. Can I use the platform_data
field to store a pointer to this structure like I would the private_data
field of struct file
in the module's open()
routine or is this reserved? It's set to NULL after device_create
so it would appear OK but I don't know for sure.
What I'd like to do is:
struct mymodule mymod; // main module structure, has a mutex called lockmx
static ssize_t mydev_store_val(struct device *dev,
struct device_attribute *attr,
const char *buf,size_t count)
{
struct mymodule *mymodp=(struct mymodule*)dev->platform_data;
if(mutex_lock_interruptible(&mymodp->lockmx))
return 0;
// get data from buf
mutex_unlock(&mymodp->lockmx);
return count;
}
DEVICE_ATTR(mydeva,S_IWUSR|S_IRUGO,NULL,mydev_store_val);
static int __init modinit(void)
{
...
dev_t dev; // alloc'ed already
myclass=class_create(THIS_MODULE,"myclass");
mydev=device_create(myclass,NULL,dev,NULL,"mydev");
mydev->platform_data=&mymod;
device_create_file(mydev,&dev_attr_mydeva);
...
}
So this will create the entry /sys/class/myclass/mydev/mydeva
which can be written to. If the platform_data
field is available then I can avoid using globals. But if it moves under me my kernel is going to oops at best and probably panic.
Such a pointer can be stored in the drvdata
field (which has been cleverly hidden so that you will not see it if you look at the definition of struct device
).
Initialize it through the fourth parameter of device_create
, and read it with dev_get_drvdata
:
mydev = device_create(myclass, NULL, dev, &mymod, "mydev");
...
struct mymodule *mymodp = dev_get_drvdata(dev);