On Tue, Aug 18, 2015 at 11:00:20AM +0100, Russell King - ARM Linux wrote:
On Tue, Aug 18, 2015 at 10:26:32AM +0200, Hans Verkuil wrote:
- /* Part 2: Initialize and register the character device */
- cdev_init(&cecdev->cdev, &cec_devnode_fops);
- cecdev->cdev.owner = owner;
- ret = cdev_add(&cecdev->cdev, MKDEV(MAJOR(cec_dev_t), cecdev->minor),
1);
- if (ret < 0) {
pr_err("%s: cdev_add failed\n", __func__);
goto error;
- }
- /* Part 3: Register the cec device */
- cecdev->dev.bus = &cec_bus_type;
- cecdev->dev.devt = MKDEV(MAJOR(cec_dev_t), cecdev->minor);
- cecdev->dev.release = cec_devnode_release;
- if (cecdev->parent)
cecdev->dev.parent = cecdev->parent;
- dev_set_name(&cecdev->dev, "cec%d", cecdev->minor);
- ret = device_register(&cecdev->dev);
It's worth pointing out that you can greatly simplify the lifetime handling (you don't need to get and put cecdev->dev) if you make the cdev a child of the cecdev->dev.
If you grep for kobj.parent in drivers/ you'll see many drivers are doing this.
cecdev->cdev.kobj.parent = &cecdev->dev.kobj;
but you will need to call device_initialize() on cecdev->dev first, and use device_add() here.
This is basically a requirement if one embeds both device and a cdev into the same structure. Trying to do get/put in the driver is racy, you need to let framework know (by setting cdve's parent to the device structure).
Thanks.