drivers/rpmsg/rpmsg_ctrl.c
Source file repositories/reference/linux-study-clean/drivers/rpmsg/rpmsg_ctrl.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/rpmsg/rpmsg_ctrl.c- Extension
.c- Size
- 5994 bytes
- Lines
- 246
- Domain
- Driver Families
- Bucket
- drivers/rpmsg
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/cdev.hlinux/device.hlinux/fs.hlinux/idr.hlinux/kernel.hlinux/module.hlinux/rpmsg.hlinux/skbuff.hlinux/slab.hlinux/uaccess.huapi/linux/rpmsg.hrpmsg_char.hrpmsg_internal.h
Detected Declarations
struct rpmsg_ctrldevfunction rpmsg_ctrldev_openfunction rpmsg_ctrldev_releasefunction rpmsg_ctrldev_ioctlfunction rpmsg_ctrldev_release_devicefunction rpmsg_ctrldev_probefunction rpmsg_ctrldev_removefunction rpmsg_ctrldev_initfunction rpmsg_ctrldev_exit
Annotated Snippet
static const struct file_operations rpmsg_ctrldev_fops = {
.owner = THIS_MODULE,
.open = rpmsg_ctrldev_open,
.release = rpmsg_ctrldev_release,
.unlocked_ioctl = rpmsg_ctrldev_ioctl,
.compat_ioctl = compat_ptr_ioctl,
};
static void rpmsg_ctrldev_release_device(struct device *dev)
{
struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
ida_free(&rpmsg_ctrl_ida, dev->id);
ida_free(&rpmsg_minor_ida, MINOR(dev->devt));
kfree(ctrldev);
}
static int rpmsg_ctrldev_probe(struct rpmsg_device *rpdev)
{
struct rpmsg_ctrldev *ctrldev;
struct device *dev;
int ret;
ctrldev = kzalloc_obj(*ctrldev);
if (!ctrldev)
return -ENOMEM;
ctrldev->rpdev = rpdev;
dev = &ctrldev->dev;
device_initialize(dev);
dev->parent = &rpdev->dev;
dev->class = &rpmsg_class;
mutex_init(&ctrldev->ctrl_lock);
cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops);
ctrldev->cdev.owner = THIS_MODULE;
ret = ida_alloc_max(&rpmsg_minor_ida, RPMSG_DEV_MAX - 1, GFP_KERNEL);
if (ret < 0)
goto free_ctrldev;
dev->devt = MKDEV(MAJOR(rpmsg_major), ret);
ret = ida_alloc(&rpmsg_ctrl_ida, GFP_KERNEL);
if (ret < 0)
goto free_minor_ida;
dev->id = ret;
dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret);
ret = cdev_device_add(&ctrldev->cdev, &ctrldev->dev);
if (ret)
goto free_ctrl_ida;
/* We can now rely on the release function for cleanup */
dev->release = rpmsg_ctrldev_release_device;
dev_set_drvdata(&rpdev->dev, ctrldev);
return ret;
free_ctrl_ida:
ida_free(&rpmsg_ctrl_ida, dev->id);
free_minor_ida:
ida_free(&rpmsg_minor_ida, MINOR(dev->devt));
free_ctrldev:
put_device(dev);
kfree(ctrldev);
return ret;
}
static void rpmsg_ctrldev_remove(struct rpmsg_device *rpdev)
{
struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
int ret;
mutex_lock(&ctrldev->ctrl_lock);
/* Destroy all endpoints */
ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_chrdev_eptdev_destroy);
if (ret)
dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
mutex_unlock(&ctrldev->ctrl_lock);
cdev_device_del(&ctrldev->cdev, &ctrldev->dev);
put_device(&ctrldev->dev);
}
static struct rpmsg_driver rpmsg_ctrldev_driver = {
.probe = rpmsg_ctrldev_probe,
.remove = rpmsg_ctrldev_remove,
Annotation
- Immediate include surface: `linux/cdev.h`, `linux/device.h`, `linux/fs.h`, `linux/idr.h`, `linux/kernel.h`, `linux/module.h`, `linux/rpmsg.h`, `linux/skbuff.h`.
- Detected declarations: `struct rpmsg_ctrldev`, `function rpmsg_ctrldev_open`, `function rpmsg_ctrldev_release`, `function rpmsg_ctrldev_ioctl`, `function rpmsg_ctrldev_release_device`, `function rpmsg_ctrldev_probe`, `function rpmsg_ctrldev_remove`, `function rpmsg_ctrldev_init`, `function rpmsg_ctrldev_exit`.
- Atlas domain: Driver Families / drivers/rpmsg.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.