Reputation: 1
How to seperate alloc_chrdev_region and cdev_add from platform driver's probe function, in order to initiate multiple instances of the same device? And where can I access related platform driver sample code with similar capability?
I have 4 instantiated devices which are working in the same way. Usually I use platform driver to operate my device, but the code I have can only initiate 1 instantiated device with .ko and insmod command, rather than multiple instances of the same device.
I tried to re-write my code. I found that the platform_driver's probe function includes alloc_chrdev_region and cdev_add. I do not know how to seperate alloc_chrdev_region and cdev_add function from platform_driver's probe function.
Following code is the device tree of my device:
mipi_csi2_rx_v_cap_pipeline_0: v_cap_pipeline@a0030000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 104 4>;
reg = <0x0 0xa0030000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
mipi_csi2_rx_v_cap_pipeline_1: v_cap_pipeline@a0034000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 105 4>;
reg = <0x0 0xa0034000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
mipi_csi2_rx_v_cap_pipeline_2: v_cap_pipeline@a0038000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 106 4>;
reg = <0x0 0xa0038000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
mipi_csi2_rx_v_cap_pipeline_3: v_cap_pipeline@a003c000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 107 4>;
reg = <0x0 0xa003c000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
Following sample code is the probe function of my platform driver:
static int fstream_probe(struct platform_device *pdev) {
struct device *dev = &pdev->dev;
dev_t devno = MKDEV(fstream_major, 0);
ret = alloc_chrdev_region(&devno, 0, DEV_NUM, DRIVER_NAME);
fstream_major = MAJOR(devno);
cdevp = (struct fstream_cdev *) kzalloc(sizeof(struct fstream_cdev)*DEV_NUM, GFP_KERNEL);
fstream_setup_cdev(cdevp);
...
/* others ignored */
PDEBUG(" init success\n");;
}
static struct of_device_id fstream_of_match[] = {
{.compatible = "xlnx,v-cap-pipeline-1.0", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, fstream_of_match);
static struct platform_driver fstream_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = fstream_of_match,
},
.probe = fstream_probe,
.remove = fstream_remove,
};
static int __init fstream_init(void) {
return platform_driver_register(&fstream_driver);
}
module_init(fstream_init);
When the probe function in my code is called 4 times, 4 major device with different major id are created under /proc/devices, which is not I expected(I want 1 major id with 4 different minor id).
Following message is the log of my device, it shows that the probe functions is called 4 times:
zynqmp#dmesg |grep fstream
[ 111.769297] st_fstream: loading out-of-tree module taints kernel.
[ 111.775514] st_fstream: unknown parameter 'st_fstream' ignored
[ 111.781314] st_fstream: unknown parameter 'st_fstream' ignored
[ 111.787429] [fstream]cdev Device number reg/allocation successed. cdev->major=243, cdev->minor=0.
[ 111.787511] [fstream]@0xa0030000 mapped to 0xffffff800bbe0000, irq=46
[ 111.787512] [fstream] init success
[ 111.787572] [fstream]cdev Device number reg/allocation successed. cdev->major=242, cdev->minor=0.
[ 111.787631] [fstream]@0xa0034000 mapped to 0xffffff800bbf0000, irq=47
[ 111.787634] [fstream] init success
[ 111.787671] [fstream]cdev Device number reg/allocation successed. cdev->major=241, cdev->minor=0.
[ 111.787730] [fstream]@0xa0038000 mapped to 0xffffff800bc00000, irq=48
[ 111.787732] [fstream] init success
[ 111.787767] [fstream]cdev Device number reg/allocation successed. cdev->major=240, cdev->minor=0.
[ 111.787826] [fstream]@0xa003c000 mapped to 0xffffff800bc10000, irq=49
[ 111.787827] [fstream] init success
Upvotes: 0
Views: 1703
Reputation: 1
AS @Ian Abbott suggests, with cdev and pdev both in my driver code, I need to do following:
Get the major id in static int __init fstream_init(void){..}, and add/init cdev in platform_driver's fstream_probe function.And with 4 instantiation of the same device in DTS, I can successfully find 4 device with the same major ID but different minor ID.
Make sure each device occupies its own global data structure, by using static array and minor id to distinguish with each other.
Also, use file->private_data and container_of to open and release cdev.
And it finally works! Thanks to all!
Upvotes: 0