Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
[sfrench/cifs-2.6.git] / drivers / staging / most / cdev / cdev.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * cdev.c - Character device component for Mostcore
4  *
5  * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
6  */
7
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/module.h>
10 #include <linux/sched.h>
11 #include <linux/fs.h>
12 #include <linux/slab.h>
13 #include <linux/device.h>
14 #include <linux/cdev.h>
15 #include <linux/poll.h>
16 #include <linux/kfifo.h>
17 #include <linux/uaccess.h>
18 #include <linux/idr.h>
19 #include "most/core.h"
20
21 static struct cdev_component {
22         dev_t devno;
23         struct ida minor_id;
24         unsigned int major;
25         struct class *class;
26         struct core_component cc;
27 } comp;
28
29 struct comp_channel {
30         wait_queue_head_t wq;
31         spinlock_t unlink;      /* synchronization lock to unlink channels */
32         struct cdev cdev;
33         struct device *dev;
34         struct mutex io_mutex;
35         struct most_interface *iface;
36         struct most_channel_config *cfg;
37         unsigned int channel_id;
38         dev_t devno;
39         size_t mbo_offs;
40         DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
41         int access_ref;
42         struct list_head list;
43 };
44
45 #define to_channel(d) container_of(d, struct comp_channel, cdev)
46 static struct list_head channel_list;
47 static spinlock_t ch_list_lock;
48
49 static inline bool ch_has_mbo(struct comp_channel *c)
50 {
51         return channel_has_mbo(c->iface, c->channel_id, &comp.cc) > 0;
52 }
53
54 static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo)
55 {
56         if (!kfifo_peek(&c->fifo, mbo)) {
57                 *mbo = most_get_mbo(c->iface, c->channel_id, &comp.cc);
58                 if (*mbo)
59                         kfifo_in(&c->fifo, mbo, 1);
60         }
61         return *mbo;
62 }
63
64 static struct comp_channel *get_channel(struct most_interface *iface, int id)
65 {
66         struct comp_channel *c, *tmp;
67         unsigned long flags;
68         int found_channel = 0;
69
70         spin_lock_irqsave(&ch_list_lock, flags);
71         list_for_each_entry_safe(c, tmp, &channel_list, list) {
72                 if ((c->iface == iface) && (c->channel_id == id)) {
73                         found_channel = 1;
74                         break;
75                 }
76         }
77         spin_unlock_irqrestore(&ch_list_lock, flags);
78         if (!found_channel)
79                 return NULL;
80         return c;
81 }
82
83 static void stop_channel(struct comp_channel *c)
84 {
85         struct mbo *mbo;
86
87         while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
88                 most_put_mbo(mbo);
89         most_stop_channel(c->iface, c->channel_id, &comp.cc);
90 }
91
92 static void destroy_cdev(struct comp_channel *c)
93 {
94         unsigned long flags;
95
96         device_destroy(comp.class, c->devno);
97         cdev_del(&c->cdev);
98         spin_lock_irqsave(&ch_list_lock, flags);
99         list_del(&c->list);
100         spin_unlock_irqrestore(&ch_list_lock, flags);
101 }
102
103 static void destroy_channel(struct comp_channel *c)
104 {
105         ida_simple_remove(&comp.minor_id, MINOR(c->devno));
106         kfifo_free(&c->fifo);
107         kfree(c);
108 }
109
110 /**
111  * comp_open - implements the syscall to open the device
112  * @inode: inode pointer
113  * @filp: file pointer
114  *
115  * This stores the channel pointer in the private data field of
116  * the file structure and activates the channel within the core.
117  */
118 static int comp_open(struct inode *inode, struct file *filp)
119 {
120         struct comp_channel *c;
121         int ret;
122
123         c = to_channel(inode->i_cdev);
124         filp->private_data = c;
125
126         if (((c->cfg->direction == MOST_CH_RX) &&
127              ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
128              ((c->cfg->direction == MOST_CH_TX) &&
129                 ((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
130                 pr_info("WARN: Access flags mismatch\n");
131                 return -EACCES;
132         }
133
134         mutex_lock(&c->io_mutex);
135         if (!c->dev) {
136                 pr_info("WARN: Device is destroyed\n");
137                 mutex_unlock(&c->io_mutex);
138                 return -ENODEV;
139         }
140
141         if (c->access_ref) {
142                 pr_info("WARN: Device is busy\n");
143                 mutex_unlock(&c->io_mutex);
144                 return -EBUSY;
145         }
146
147         c->mbo_offs = 0;
148         ret = most_start_channel(c->iface, c->channel_id, &comp.cc);
149         if (!ret)
150                 c->access_ref = 1;
151         mutex_unlock(&c->io_mutex);
152         return ret;
153 }
154
155 /**
156  * comp_close - implements the syscall to close the device
157  * @inode: inode pointer
158  * @filp: file pointer
159  *
160  * This stops the channel within the core.
161  */
162 static int comp_close(struct inode *inode, struct file *filp)
163 {
164         struct comp_channel *c = to_channel(inode->i_cdev);
165
166         mutex_lock(&c->io_mutex);
167         spin_lock(&c->unlink);
168         c->access_ref = 0;
169         spin_unlock(&c->unlink);
170         if (c->dev) {
171                 stop_channel(c);
172                 mutex_unlock(&c->io_mutex);
173         } else {
174                 mutex_unlock(&c->io_mutex);
175                 destroy_channel(c);
176         }
177         return 0;
178 }
179
180 /**
181  * comp_write - implements the syscall to write to the device
182  * @filp: file pointer
183  * @buf: pointer to user buffer
184  * @count: number of bytes to write
185  * @offset: offset from where to start writing
186  */
187 static ssize_t comp_write(struct file *filp, const char __user *buf,
188                           size_t count, loff_t *offset)
189 {
190         int ret;
191         size_t to_copy, left;
192         struct mbo *mbo = NULL;
193         struct comp_channel *c = filp->private_data;
194
195         mutex_lock(&c->io_mutex);
196         while (c->dev && !ch_get_mbo(c, &mbo)) {
197                 mutex_unlock(&c->io_mutex);
198
199                 if ((filp->f_flags & O_NONBLOCK))
200                         return -EAGAIN;
201                 if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev))
202                         return -ERESTARTSYS;
203                 mutex_lock(&c->io_mutex);
204         }
205
206         if (unlikely(!c->dev)) {
207                 ret = -ENODEV;
208                 goto unlock;
209         }
210
211         to_copy = min(count, c->cfg->buffer_size - c->mbo_offs);
212         left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy);
213         if (left == to_copy) {
214                 ret = -EFAULT;
215                 goto unlock;
216         }
217
218         c->mbo_offs += to_copy - left;
219         if (c->mbo_offs >= c->cfg->buffer_size ||
220             c->cfg->data_type == MOST_CH_CONTROL ||
221             c->cfg->data_type == MOST_CH_ASYNC) {
222                 kfifo_skip(&c->fifo);
223                 mbo->buffer_length = c->mbo_offs;
224                 c->mbo_offs = 0;
225                 most_submit_mbo(mbo);
226         }
227
228         ret = to_copy - left;
229 unlock:
230         mutex_unlock(&c->io_mutex);
231         return ret;
232 }
233
234 /**
235  * comp_read - implements the syscall to read from the device
236  * @filp: file pointer
237  * @buf: pointer to user buffer
238  * @count: number of bytes to read
239  * @offset: offset from where to start reading
240  */
241 static ssize_t
242 comp_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
243 {
244         size_t to_copy, not_copied, copied;
245         struct mbo *mbo;
246         struct comp_channel *c = filp->private_data;
247
248         mutex_lock(&c->io_mutex);
249         while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
250                 mutex_unlock(&c->io_mutex);
251                 if (filp->f_flags & O_NONBLOCK)
252                         return -EAGAIN;
253                 if (wait_event_interruptible(c->wq,
254                                              (!kfifo_is_empty(&c->fifo) ||
255                                               (!c->dev))))
256                         return -ERESTARTSYS;
257                 mutex_lock(&c->io_mutex);
258         }
259
260         /* make sure we don't submit to gone devices */
261         if (unlikely(!c->dev)) {
262                 mutex_unlock(&c->io_mutex);
263                 return -ENODEV;
264         }
265
266         to_copy = min_t(size_t,
267                         count,
268                         mbo->processed_length - c->mbo_offs);
269
270         not_copied = copy_to_user(buf,
271                                   mbo->virt_address + c->mbo_offs,
272                                   to_copy);
273
274         copied = to_copy - not_copied;
275
276         c->mbo_offs += copied;
277         if (c->mbo_offs >= mbo->processed_length) {
278                 kfifo_skip(&c->fifo);
279                 most_put_mbo(mbo);
280                 c->mbo_offs = 0;
281         }
282         mutex_unlock(&c->io_mutex);
283         return copied;
284 }
285
286 static __poll_t comp_poll(struct file *filp, poll_table *wait)
287 {
288         struct comp_channel *c = filp->private_data;
289         __poll_t mask = 0;
290
291         poll_wait(filp, &c->wq, wait);
292
293         if (c->cfg->direction == MOST_CH_RX) {
294                 if (!kfifo_is_empty(&c->fifo))
295                         mask |= POLLIN | POLLRDNORM;
296         } else {
297                 if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c))
298                         mask |= POLLOUT | POLLWRNORM;
299         }
300         return mask;
301 }
302
303 /**
304  * Initialization of struct file_operations
305  */
306 static const struct file_operations channel_fops = {
307         .owner = THIS_MODULE,
308         .read = comp_read,
309         .write = comp_write,
310         .open = comp_open,
311         .release = comp_close,
312         .poll = comp_poll,
313 };
314
315 /**
316  * comp_disconnect_channel - disconnect a channel
317  * @iface: pointer to interface instance
318  * @channel_id: channel index
319  *
320  * This frees allocated memory and removes the cdev that represents this
321  * channel in user space.
322  */
323 static int comp_disconnect_channel(struct most_interface *iface, int channel_id)
324 {
325         struct comp_channel *c;
326
327         if (!iface) {
328                 pr_info("Bad interface pointer\n");
329                 return -EINVAL;
330         }
331
332         c = get_channel(iface, channel_id);
333         if (!c)
334                 return -ENXIO;
335
336         mutex_lock(&c->io_mutex);
337         spin_lock(&c->unlink);
338         c->dev = NULL;
339         spin_unlock(&c->unlink);
340         destroy_cdev(c);
341         if (c->access_ref) {
342                 stop_channel(c);
343                 wake_up_interruptible(&c->wq);
344                 mutex_unlock(&c->io_mutex);
345         } else {
346                 mutex_unlock(&c->io_mutex);
347                 destroy_channel(c);
348         }
349         return 0;
350 }
351
352 /**
353  * comp_rx_completion - completion handler for rx channels
354  * @mbo: pointer to buffer object that has completed
355  *
356  * This searches for the channel linked to this MBO and stores it in the local
357  * fifo buffer.
358  */
359 static int comp_rx_completion(struct mbo *mbo)
360 {
361         struct comp_channel *c;
362
363         if (!mbo)
364                 return -EINVAL;
365
366         c = get_channel(mbo->ifp, mbo->hdm_channel_id);
367         if (!c)
368                 return -ENXIO;
369
370         spin_lock(&c->unlink);
371         if (!c->access_ref || !c->dev) {
372                 spin_unlock(&c->unlink);
373                 return -ENODEV;
374         }
375         kfifo_in(&c->fifo, &mbo, 1);
376         spin_unlock(&c->unlink);
377 #ifdef DEBUG_MESG
378         if (kfifo_is_full(&c->fifo))
379                 pr_info("WARN: Fifo is full\n");
380 #endif
381         wake_up_interruptible(&c->wq);
382         return 0;
383 }
384
385 /**
386  * comp_tx_completion - completion handler for tx channels
387  * @iface: pointer to interface instance
388  * @channel_id: channel index/ID
389  *
390  * This wakes sleeping processes in the wait-queue.
391  */
392 static int comp_tx_completion(struct most_interface *iface, int channel_id)
393 {
394         struct comp_channel *c;
395
396         if (!iface) {
397                 pr_info("Bad interface pointer\n");
398                 return -EINVAL;
399         }
400         if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
401                 pr_info("Channel ID out of range\n");
402                 return -EINVAL;
403         }
404
405         c = get_channel(iface, channel_id);
406         if (!c)
407                 return -ENXIO;
408         wake_up_interruptible(&c->wq);
409         return 0;
410 }
411
412 /**
413  * comp_probe - probe function of the driver module
414  * @iface: pointer to interface instance
415  * @channel_id: channel index/ID
416  * @cfg: pointer to actual channel configuration
417  * @name: name of the device to be created
418  *
419  * This allocates achannel object and creates the device node in /dev
420  *
421  * Returns 0 on success or error code otherwise.
422  */
423 static int comp_probe(struct most_interface *iface, int channel_id,
424                       struct most_channel_config *cfg, char *name)
425 {
426         struct comp_channel *c;
427         unsigned long cl_flags;
428         int retval;
429         int current_minor;
430
431         if ((!iface) || (!cfg) || (!name)) {
432                 pr_info("Probing component with bad arguments");
433                 return -EINVAL;
434         }
435         c = get_channel(iface, channel_id);
436         if (c)
437                 return -EEXIST;
438
439         current_minor = ida_simple_get(&comp.minor_id, 0, 0, GFP_KERNEL);
440         if (current_minor < 0)
441                 return current_minor;
442
443         c = kzalloc(sizeof(*c), GFP_KERNEL);
444         if (!c) {
445                 retval = -ENOMEM;
446                 goto error_alloc_channel;
447         }
448
449         c->devno = MKDEV(comp.major, current_minor);
450         cdev_init(&c->cdev, &channel_fops);
451         c->cdev.owner = THIS_MODULE;
452         cdev_add(&c->cdev, c->devno, 1);
453         c->iface = iface;
454         c->cfg = cfg;
455         c->channel_id = channel_id;
456         c->access_ref = 0;
457         spin_lock_init(&c->unlink);
458         INIT_KFIFO(c->fifo);
459         retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
460         if (retval) {
461                 pr_info("failed to alloc channel kfifo");
462                 goto error_alloc_kfifo;
463         }
464         init_waitqueue_head(&c->wq);
465         mutex_init(&c->io_mutex);
466         spin_lock_irqsave(&ch_list_lock, cl_flags);
467         list_add_tail(&c->list, &channel_list);
468         spin_unlock_irqrestore(&ch_list_lock, cl_flags);
469         c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name);
470
471         if (IS_ERR(c->dev)) {
472                 retval = PTR_ERR(c->dev);
473                 pr_info("failed to create new device node %s\n", name);
474                 goto error_create_device;
475         }
476         kobject_uevent(&c->dev->kobj, KOBJ_ADD);
477         return 0;
478
479 error_create_device:
480         kfifo_free(&c->fifo);
481         list_del(&c->list);
482 error_alloc_kfifo:
483         cdev_del(&c->cdev);
484         kfree(c);
485 error_alloc_channel:
486         ida_simple_remove(&comp.minor_id, current_minor);
487         return retval;
488 }
489
490 static struct cdev_component comp = {
491         .cc = {
492                 .name = "cdev",
493                 .probe_channel = comp_probe,
494                 .disconnect_channel = comp_disconnect_channel,
495                 .rx_completion = comp_rx_completion,
496                 .tx_completion = comp_tx_completion,
497         },
498 };
499
500 static int __init mod_init(void)
501 {
502         int err;
503
504         pr_info("init()\n");
505
506         comp.class = class_create(THIS_MODULE, "most_cdev");
507         if (IS_ERR(comp.class)) {
508                 pr_info("No udev support.\n");
509                 return PTR_ERR(comp.class);
510         }
511
512         INIT_LIST_HEAD(&channel_list);
513         spin_lock_init(&ch_list_lock);
514         ida_init(&comp.minor_id);
515
516         err = alloc_chrdev_region(&comp.devno, 0, 50, "cdev");
517         if (err < 0)
518                 goto dest_ida;
519         comp.major = MAJOR(comp.devno);
520         err = most_register_component(&comp.cc);
521         if (err)
522                 goto free_cdev;
523         return 0;
524
525 free_cdev:
526         unregister_chrdev_region(comp.devno, 1);
527 dest_ida:
528         ida_destroy(&comp.minor_id);
529         class_destroy(comp.class);
530         return err;
531 }
532
533 static void __exit mod_exit(void)
534 {
535         struct comp_channel *c, *tmp;
536
537         pr_info("exit module\n");
538
539         most_deregister_component(&comp.cc);
540
541         list_for_each_entry_safe(c, tmp, &channel_list, list) {
542                 destroy_cdev(c);
543                 destroy_channel(c);
544         }
545         unregister_chrdev_region(comp.devno, 1);
546         ida_destroy(&comp.minor_id);
547         class_destroy(comp.class);
548 }
549
550 module_init(mod_init);
551 module_exit(mod_exit);
552 MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
553 MODULE_LICENSE("GPL");
554 MODULE_DESCRIPTION("character device component for mostcore");