Lines Matching +full:rpmsg +full:- +full:name
1 // SPDX-License-Identifier: GPL-2.0
9 * Based on rpmsg performance statistics driver by Michal Simek, which in turn
10 * was based on TI & Google OMX rpmsg driver.
19 #include <linux/rpmsg.h>
23 #include <uapi/linux/rpmsg.h>
43 * struct rpmsg_ctrldev - control device for instantiating endpoint devices
44 * @rpdev: underlaying rpmsg device
55 * struct rpmsg_eptdev - endpoint device context
58 * @rpdev: underlaying rpmsg device
61 * @ept: rpmsg endpoint reference, when open
85 mutex_lock(&eptdev->ept_lock); in rpmsg_eptdev_destroy()
86 if (eptdev->ept) { in rpmsg_eptdev_destroy()
87 rpmsg_destroy_ept(eptdev->ept); in rpmsg_eptdev_destroy()
88 eptdev->ept = NULL; in rpmsg_eptdev_destroy()
90 mutex_unlock(&eptdev->ept_lock); in rpmsg_eptdev_destroy()
93 wake_up_interruptible(&eptdev->readq); in rpmsg_eptdev_destroy()
95 device_del(&eptdev->dev); in rpmsg_eptdev_destroy()
96 put_device(&eptdev->dev); in rpmsg_eptdev_destroy()
109 return -ENOMEM; in rpmsg_ept_cb()
113 spin_lock(&eptdev->queue_lock); in rpmsg_ept_cb()
114 skb_queue_tail(&eptdev->queue, skb); in rpmsg_ept_cb()
115 spin_unlock(&eptdev->queue_lock); in rpmsg_ept_cb()
118 wake_up_interruptible(&eptdev->readq); in rpmsg_ept_cb()
125 struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev); in rpmsg_eptdev_open()
127 struct rpmsg_device *rpdev = eptdev->rpdev; in rpmsg_eptdev_open()
128 struct device *dev = &eptdev->dev; in rpmsg_eptdev_open()
132 ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo); in rpmsg_eptdev_open()
134 dev_err(dev, "failed to open %s\n", eptdev->chinfo.name); in rpmsg_eptdev_open()
136 return -EINVAL; in rpmsg_eptdev_open()
139 eptdev->ept = ept; in rpmsg_eptdev_open()
140 filp->private_data = eptdev; in rpmsg_eptdev_open()
147 struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev); in rpmsg_eptdev_release()
148 struct device *dev = &eptdev->dev; in rpmsg_eptdev_release()
152 mutex_lock(&eptdev->ept_lock); in rpmsg_eptdev_release()
153 if (eptdev->ept) { in rpmsg_eptdev_release()
154 rpmsg_destroy_ept(eptdev->ept); in rpmsg_eptdev_release()
155 eptdev->ept = NULL; in rpmsg_eptdev_release()
157 mutex_unlock(&eptdev->ept_lock); in rpmsg_eptdev_release()
160 while (!skb_queue_empty(&eptdev->queue)) { in rpmsg_eptdev_release()
161 skb = skb_dequeue(&eptdev->queue); in rpmsg_eptdev_release()
173 struct rpmsg_eptdev *eptdev = filp->private_data; in rpmsg_eptdev_read()
178 if (!eptdev->ept) in rpmsg_eptdev_read()
179 return -EPIPE; in rpmsg_eptdev_read()
181 spin_lock_irqsave(&eptdev->queue_lock, flags); in rpmsg_eptdev_read()
184 if (skb_queue_empty(&eptdev->queue)) { in rpmsg_eptdev_read()
185 spin_unlock_irqrestore(&eptdev->queue_lock, flags); in rpmsg_eptdev_read()
187 if (filp->f_flags & O_NONBLOCK) in rpmsg_eptdev_read()
188 return -EAGAIN; in rpmsg_eptdev_read()
191 if (wait_event_interruptible(eptdev->readq, in rpmsg_eptdev_read()
192 !skb_queue_empty(&eptdev->queue) || in rpmsg_eptdev_read()
193 !eptdev->ept)) in rpmsg_eptdev_read()
194 return -ERESTARTSYS; in rpmsg_eptdev_read()
197 if (!eptdev->ept) in rpmsg_eptdev_read()
198 return -EPIPE; in rpmsg_eptdev_read()
200 spin_lock_irqsave(&eptdev->queue_lock, flags); in rpmsg_eptdev_read()
203 skb = skb_dequeue(&eptdev->queue); in rpmsg_eptdev_read()
204 spin_unlock_irqrestore(&eptdev->queue_lock, flags); in rpmsg_eptdev_read()
206 return -EFAULT; in rpmsg_eptdev_read()
208 use = min_t(size_t, len, skb->len); in rpmsg_eptdev_read()
209 if (copy_to_user(buf, skb->data, use)) in rpmsg_eptdev_read()
210 use = -EFAULT; in rpmsg_eptdev_read()
220 struct rpmsg_eptdev *eptdev = filp->private_data; in rpmsg_eptdev_write()
228 if (mutex_lock_interruptible(&eptdev->ept_lock)) { in rpmsg_eptdev_write()
229 ret = -ERESTARTSYS; in rpmsg_eptdev_write()
233 if (!eptdev->ept) { in rpmsg_eptdev_write()
234 ret = -EPIPE; in rpmsg_eptdev_write()
238 if (filp->f_flags & O_NONBLOCK) in rpmsg_eptdev_write()
239 ret = rpmsg_trysend(eptdev->ept, kbuf, len); in rpmsg_eptdev_write()
241 ret = rpmsg_send(eptdev->ept, kbuf, len); in rpmsg_eptdev_write()
244 mutex_unlock(&eptdev->ept_lock); in rpmsg_eptdev_write()
253 struct rpmsg_eptdev *eptdev = filp->private_data; in rpmsg_eptdev_poll()
256 if (!eptdev->ept) in rpmsg_eptdev_poll()
259 poll_wait(filp, &eptdev->readq, wait); in rpmsg_eptdev_poll()
261 if (!skb_queue_empty(&eptdev->queue)) in rpmsg_eptdev_poll()
264 mask |= rpmsg_poll(eptdev->ept, filp, wait); in rpmsg_eptdev_poll()
272 struct rpmsg_eptdev *eptdev = fp->private_data; in rpmsg_eptdev_ioctl()
275 return -EINVAL; in rpmsg_eptdev_ioctl()
277 return rpmsg_eptdev_destroy(&eptdev->dev, NULL); in rpmsg_eptdev_ioctl()
296 return sprintf(buf, "%s\n", eptdev->chinfo.name); in name_show()
298 static DEVICE_ATTR_RO(name);
305 return sprintf(buf, "%d\n", eptdev->chinfo.src); in src_show()
314 return sprintf(buf, "%d\n", eptdev->chinfo.dst); in dst_show()
330 ida_simple_remove(&rpmsg_ept_ida, dev->id); in rpmsg_eptdev_release_device()
331 ida_simple_remove(&rpmsg_minor_ida, MINOR(eptdev->dev.devt)); in rpmsg_eptdev_release_device()
332 cdev_del(&eptdev->cdev); in rpmsg_eptdev_release_device()
339 struct rpmsg_device *rpdev = ctrldev->rpdev; in rpmsg_eptdev_create()
346 return -ENOMEM; in rpmsg_eptdev_create()
348 dev = &eptdev->dev; in rpmsg_eptdev_create()
349 eptdev->rpdev = rpdev; in rpmsg_eptdev_create()
350 eptdev->chinfo = chinfo; in rpmsg_eptdev_create()
352 mutex_init(&eptdev->ept_lock); in rpmsg_eptdev_create()
353 spin_lock_init(&eptdev->queue_lock); in rpmsg_eptdev_create()
354 skb_queue_head_init(&eptdev->queue); in rpmsg_eptdev_create()
355 init_waitqueue_head(&eptdev->readq); in rpmsg_eptdev_create()
358 dev->class = rpmsg_class; in rpmsg_eptdev_create()
359 dev->parent = &ctrldev->dev; in rpmsg_eptdev_create()
360 dev->groups = rpmsg_eptdev_groups; in rpmsg_eptdev_create()
363 cdev_init(&eptdev->cdev, &rpmsg_eptdev_fops); in rpmsg_eptdev_create()
364 eptdev->cdev.owner = THIS_MODULE; in rpmsg_eptdev_create()
369 dev->devt = MKDEV(MAJOR(rpmsg_major), ret); in rpmsg_eptdev_create()
374 dev->id = ret; in rpmsg_eptdev_create()
375 dev_set_name(dev, "rpmsg%d", ret); in rpmsg_eptdev_create()
377 ret = cdev_add(&eptdev->cdev, dev->devt, 1); in rpmsg_eptdev_create()
382 dev->release = rpmsg_eptdev_release_device; in rpmsg_eptdev_create()
393 ida_simple_remove(&rpmsg_ept_ida, dev->id); in rpmsg_eptdev_create()
395 ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); in rpmsg_eptdev_create()
405 struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev); in rpmsg_ctrldev_open()
407 get_device(&ctrldev->dev); in rpmsg_ctrldev_open()
408 filp->private_data = ctrldev; in rpmsg_ctrldev_open()
415 struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev); in rpmsg_ctrldev_release()
417 put_device(&ctrldev->dev); in rpmsg_ctrldev_release()
425 struct rpmsg_ctrldev *ctrldev = fp->private_data; in rpmsg_ctrldev_ioctl()
431 return -EINVAL; in rpmsg_ctrldev_ioctl()
434 return -EFAULT; in rpmsg_ctrldev_ioctl()
436 memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE); in rpmsg_ctrldev_ioctl()
437 chinfo.name[RPMSG_NAME_SIZE-1] = '\0'; in rpmsg_ctrldev_ioctl()
456 ida_simple_remove(&rpmsg_ctrl_ida, dev->id); in rpmsg_ctrldev_release_device()
457 ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); in rpmsg_ctrldev_release_device()
458 cdev_del(&ctrldev->cdev); in rpmsg_ctrldev_release_device()
470 return -ENOMEM; in rpmsg_chrdev_probe()
472 ctrldev->rpdev = rpdev; in rpmsg_chrdev_probe()
474 dev = &ctrldev->dev; in rpmsg_chrdev_probe()
476 dev->parent = &rpdev->dev; in rpmsg_chrdev_probe()
477 dev->class = rpmsg_class; in rpmsg_chrdev_probe()
479 cdev_init(&ctrldev->cdev, &rpmsg_ctrldev_fops); in rpmsg_chrdev_probe()
480 ctrldev->cdev.owner = THIS_MODULE; in rpmsg_chrdev_probe()
485 dev->devt = MKDEV(MAJOR(rpmsg_major), ret); in rpmsg_chrdev_probe()
490 dev->id = ret; in rpmsg_chrdev_probe()
491 dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret); in rpmsg_chrdev_probe()
493 ret = cdev_add(&ctrldev->cdev, dev->devt, 1); in rpmsg_chrdev_probe()
498 dev->release = rpmsg_ctrldev_release_device; in rpmsg_chrdev_probe()
502 dev_err(&rpdev->dev, "device_add failed: %d\n", ret); in rpmsg_chrdev_probe()
506 dev_set_drvdata(&rpdev->dev, ctrldev); in rpmsg_chrdev_probe()
511 ida_simple_remove(&rpmsg_ctrl_ida, dev->id); in rpmsg_chrdev_probe()
513 ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); in rpmsg_chrdev_probe()
523 struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev); in rpmsg_chrdev_remove()
527 ret = device_for_each_child(&ctrldev->dev, NULL, rpmsg_eptdev_destroy); in rpmsg_chrdev_remove()
529 dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret); in rpmsg_chrdev_remove()
531 device_del(&ctrldev->dev); in rpmsg_chrdev_remove()
532 put_device(&ctrldev->dev); in rpmsg_chrdev_remove()
539 .name = "rpmsg_chrdev",
547 ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg"); in rpmsg_char_init()
549 pr_err("rpmsg: failed to allocate char dev region\n"); in rpmsg_char_init()
553 rpmsg_class = class_create(THIS_MODULE, "rpmsg"); in rpmsg_char_init()
555 pr_err("failed to create rpmsg class\n"); in rpmsg_char_init()
562 pr_err("rpmsgchr: failed to register rpmsg driver\n"); in rpmsg_char_init()
579 MODULE_ALIAS("rpmsg:rpmsg_chrdev");