[go: nahoru, domu]

uio.c revision 02683ffdf655b4ae15245376ba6fea6d9e5829a6
1/*
2 * drivers/uio/uio.c
3 *
4 * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
5 * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
6 * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de>
7 * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
8 *
9 * Userspace IO
10 *
11 * Base Functions
12 *
13 * Licensed under the GPLv2 only.
14 */
15
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/poll.h>
19#include <linux/device.h>
20#include <linux/mm.h>
21#include <linux/idr.h>
22#include <linux/string.h>
23#include <linux/kobject.h>
24#include <linux/uio_driver.h>
25
26#define UIO_MAX_DEVICES 255
27
28struct uio_device {
29	struct module		*owner;
30	struct device		*dev;
31	int			minor;
32	atomic_t		event;
33	struct fasync_struct	*async_queue;
34	wait_queue_head_t	wait;
35	int			vma_count;
36	struct uio_info		*info;
37	struct kobject		*map_dir;
38};
39
40static int uio_major;
41static DEFINE_IDR(uio_idr);
42static const struct file_operations uio_fops;
43
44/* UIO class infrastructure */
45static struct uio_class {
46	struct kref kref;
47	struct class *class;
48} *uio_class;
49
50/*
51 * attributes
52 */
53
54struct uio_map {
55	struct kobject kobj;
56	struct uio_mem *mem;
57};
58#define to_map(map) container_of(map, struct uio_map, kobj)
59
60static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
61{
62	return sprintf(buf, "0x%lx\n", mem->addr);
63}
64
65static ssize_t map_size_show(struct uio_mem *mem, char *buf)
66{
67	return sprintf(buf, "0x%lx\n", mem->size);
68}
69
70static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
71{
72	return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
73}
74
75struct uio_sysfs_entry {
76	struct attribute attr;
77	ssize_t (*show)(struct uio_mem *, char *);
78	ssize_t (*store)(struct uio_mem *, const char *, size_t);
79};
80
81static struct uio_sysfs_entry addr_attribute =
82	__ATTR(addr, S_IRUGO, map_addr_show, NULL);
83static struct uio_sysfs_entry size_attribute =
84	__ATTR(size, S_IRUGO, map_size_show, NULL);
85static struct uio_sysfs_entry offset_attribute =
86	__ATTR(offset, S_IRUGO, map_offset_show, NULL);
87
88static struct attribute *attrs[] = {
89	&addr_attribute.attr,
90	&size_attribute.attr,
91	&offset_attribute.attr,
92	NULL,	/* need to NULL terminate the list of attributes */
93};
94
95static void map_release(struct kobject *kobj)
96{
97	struct uio_map *map = to_map(kobj);
98	kfree(map);
99}
100
101static ssize_t map_type_show(struct kobject *kobj, struct attribute *attr,
102			     char *buf)
103{
104	struct uio_map *map = to_map(kobj);
105	struct uio_mem *mem = map->mem;
106	struct uio_sysfs_entry *entry;
107
108	entry = container_of(attr, struct uio_sysfs_entry, attr);
109
110	if (!entry->show)
111		return -EIO;
112
113	return entry->show(mem, buf);
114}
115
116static struct sysfs_ops uio_sysfs_ops = {
117	.show = map_type_show,
118};
119
120static struct kobj_type map_attr_type = {
121	.release	= map_release,
122	.sysfs_ops	= &uio_sysfs_ops,
123	.default_attrs	= attrs,
124};
125
126static ssize_t show_name(struct device *dev,
127			 struct device_attribute *attr, char *buf)
128{
129	struct uio_device *idev = dev_get_drvdata(dev);
130	if (idev)
131		return sprintf(buf, "%s\n", idev->info->name);
132	else
133		return -ENODEV;
134}
135static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
136
137static ssize_t show_version(struct device *dev,
138			    struct device_attribute *attr, char *buf)
139{
140	struct uio_device *idev = dev_get_drvdata(dev);
141	if (idev)
142		return sprintf(buf, "%s\n", idev->info->version);
143	else
144		return -ENODEV;
145}
146static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
147
148static ssize_t show_event(struct device *dev,
149			  struct device_attribute *attr, char *buf)
150{
151	struct uio_device *idev = dev_get_drvdata(dev);
152	if (idev)
153		return sprintf(buf, "%u\n",
154				(unsigned int)atomic_read(&idev->event));
155	else
156		return -ENODEV;
157}
158static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
159
160static struct attribute *uio_attrs[] = {
161	&dev_attr_name.attr,
162	&dev_attr_version.attr,
163	&dev_attr_event.attr,
164	NULL,
165};
166
167static struct attribute_group uio_attr_grp = {
168	.attrs = uio_attrs,
169};
170
171/*
172 * device functions
173 */
174static int uio_dev_add_attributes(struct uio_device *idev)
175{
176	int ret;
177	int mi;
178	int map_found = 0;
179	struct uio_mem *mem;
180	struct uio_map *map;
181
182	ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
183	if (ret)
184		goto err_group;
185
186	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
187		mem = &idev->info->mem[mi];
188		if (mem->size == 0)
189			break;
190		if (!map_found) {
191			map_found = 1;
192			idev->map_dir = kobject_create_and_add("maps",
193							&idev->dev->kobj);
194			if (!idev->map_dir)
195				goto err;
196		}
197		map = kzalloc(sizeof(*map), GFP_KERNEL);
198		if (!map)
199			goto err;
200		kobject_init(&map->kobj, &map_attr_type);
201		map->mem = mem;
202		mem->map = map;
203		ret = kobject_add(&map->kobj, idev->map_dir, "map%d", mi);
204		if (ret)
205			goto err;
206		ret = kobject_uevent(&map->kobj, KOBJ_ADD);
207		if (ret)
208			goto err;
209	}
210
211	return 0;
212
213err:
214	for (mi--; mi>=0; mi--) {
215		mem = &idev->info->mem[mi];
216		map = mem->map;
217		kobject_put(&map->kobj);
218	}
219	kobject_put(idev->map_dir);
220	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
221err_group:
222	dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
223	return ret;
224}
225
226static void uio_dev_del_attributes(struct uio_device *idev)
227{
228	int mi;
229	struct uio_mem *mem;
230	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
231		mem = &idev->info->mem[mi];
232		if (mem->size == 0)
233			break;
234		kobject_put(&mem->map->kobj);
235	}
236	kobject_put(idev->map_dir);
237	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
238}
239
240static int uio_get_minor(struct uio_device *idev)
241{
242	static DEFINE_MUTEX(minor_lock);
243	int retval = -ENOMEM;
244	int id;
245
246	mutex_lock(&minor_lock);
247	if (idr_pre_get(&uio_idr, GFP_KERNEL) == 0)
248		goto exit;
249
250	retval = idr_get_new(&uio_idr, idev, &id);
251	if (retval < 0) {
252		if (retval == -EAGAIN)
253			retval = -ENOMEM;
254		goto exit;
255	}
256	idev->minor = id & MAX_ID_MASK;
257exit:
258	mutex_unlock(&minor_lock);
259	return retval;
260}
261
262static void uio_free_minor(struct uio_device *idev)
263{
264	idr_remove(&uio_idr, idev->minor);
265}
266
267/**
268 * uio_event_notify - trigger an interrupt event
269 * @info: UIO device capabilities
270 */
271void uio_event_notify(struct uio_info *info)
272{
273	struct uio_device *idev = info->uio_dev;
274
275	atomic_inc(&idev->event);
276	wake_up_interruptible(&idev->wait);
277	kill_fasync(&idev->async_queue, SIGIO, POLL_IN);
278}
279EXPORT_SYMBOL_GPL(uio_event_notify);
280
281/**
282 * uio_interrupt - hardware interrupt handler
283 * @irq: IRQ number, can be UIO_IRQ_CYCLIC for cyclic timer
284 * @dev_id: Pointer to the devices uio_device structure
285 */
286static irqreturn_t uio_interrupt(int irq, void *dev_id)
287{
288	struct uio_device *idev = (struct uio_device *)dev_id;
289	irqreturn_t ret = idev->info->handler(irq, idev->info);
290
291	if (ret == IRQ_HANDLED)
292		uio_event_notify(idev->info);
293
294	return ret;
295}
296
297struct uio_listener {
298	struct uio_device *dev;
299	s32 event_count;
300};
301
302static int uio_open(struct inode *inode, struct file *filep)
303{
304	struct uio_device *idev;
305	struct uio_listener *listener;
306	int ret = 0;
307
308	lock_kernel();
309	idev = idr_find(&uio_idr, iminor(inode));
310	if (!idev) {
311		ret = -ENODEV;
312		goto out;
313	}
314
315	if (!try_module_get(idev->owner)) {
316		ret = -ENODEV;
317		goto out;
318	}
319
320	listener = kmalloc(sizeof(*listener), GFP_KERNEL);
321	if (!listener) {
322		ret = -ENOMEM;
323		goto err_alloc_listener;
324	}
325
326	listener->dev = idev;
327	listener->event_count = atomic_read(&idev->event);
328	filep->private_data = listener;
329
330	if (idev->info->open) {
331		ret = idev->info->open(idev->info, inode);
332		if (ret)
333			goto err_infoopen;
334	}
335	unlock_kernel();
336	return 0;
337
338err_infoopen:
339
340	kfree(listener);
341err_alloc_listener:
342
343	module_put(idev->owner);
344
345out:
346	unlock_kernel();
347	return ret;
348}
349
350static int uio_fasync(int fd, struct file *filep, int on)
351{
352	struct uio_listener *listener = filep->private_data;
353	struct uio_device *idev = listener->dev;
354
355	return fasync_helper(fd, filep, on, &idev->async_queue);
356}
357
358static int uio_release(struct inode *inode, struct file *filep)
359{
360	int ret = 0;
361	struct uio_listener *listener = filep->private_data;
362	struct uio_device *idev = listener->dev;
363
364	if (idev->info->release)
365		ret = idev->info->release(idev->info, inode);
366
367	module_put(idev->owner);
368
369	if (filep->f_flags & FASYNC)
370		ret = uio_fasync(-1, filep, 0);
371	kfree(listener);
372	return ret;
373}
374
375static unsigned int uio_poll(struct file *filep, poll_table *wait)
376{
377	struct uio_listener *listener = filep->private_data;
378	struct uio_device *idev = listener->dev;
379
380	if (idev->info->irq == UIO_IRQ_NONE)
381		return -EIO;
382
383	poll_wait(filep, &idev->wait, wait);
384	if (listener->event_count != atomic_read(&idev->event))
385		return POLLIN | POLLRDNORM;
386	return 0;
387}
388
389static ssize_t uio_read(struct file *filep, char __user *buf,
390			size_t count, loff_t *ppos)
391{
392	struct uio_listener *listener = filep->private_data;
393	struct uio_device *idev = listener->dev;
394	DECLARE_WAITQUEUE(wait, current);
395	ssize_t retval;
396	s32 event_count;
397
398	if (idev->info->irq == UIO_IRQ_NONE)
399		return -EIO;
400
401	if (count != sizeof(s32))
402		return -EINVAL;
403
404	add_wait_queue(&idev->wait, &wait);
405
406	do {
407		set_current_state(TASK_INTERRUPTIBLE);
408
409		event_count = atomic_read(&idev->event);
410		if (event_count != listener->event_count) {
411			if (copy_to_user(buf, &event_count, count))
412				retval = -EFAULT;
413			else {
414				listener->event_count = event_count;
415				retval = count;
416			}
417			break;
418		}
419
420		if (filep->f_flags & O_NONBLOCK) {
421			retval = -EAGAIN;
422			break;
423		}
424
425		if (signal_pending(current)) {
426			retval = -ERESTARTSYS;
427			break;
428		}
429		schedule();
430	} while (1);
431
432	__set_current_state(TASK_RUNNING);
433	remove_wait_queue(&idev->wait, &wait);
434
435	return retval;
436}
437
438static ssize_t uio_write(struct file *filep, const char __user *buf,
439			size_t count, loff_t *ppos)
440{
441	struct uio_listener *listener = filep->private_data;
442	struct uio_device *idev = listener->dev;
443	ssize_t retval;
444	s32 irq_on;
445
446	if (idev->info->irq == UIO_IRQ_NONE)
447		return -EIO;
448
449	if (count != sizeof(s32))
450		return -EINVAL;
451
452	if (!idev->info->irqcontrol)
453		return -ENOSYS;
454
455	if (copy_from_user(&irq_on, buf, count))
456		return -EFAULT;
457
458	retval = idev->info->irqcontrol(idev->info, irq_on);
459
460	return retval ? retval : sizeof(s32);
461}
462
463static int uio_find_mem_index(struct vm_area_struct *vma)
464{
465	int mi;
466	struct uio_device *idev = vma->vm_private_data;
467
468	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
469		if (idev->info->mem[mi].size == 0)
470			return -1;
471		if (vma->vm_pgoff == mi)
472			return mi;
473	}
474	return -1;
475}
476
477static void uio_vma_open(struct vm_area_struct *vma)
478{
479	struct uio_device *idev = vma->vm_private_data;
480	idev->vma_count++;
481}
482
483static void uio_vma_close(struct vm_area_struct *vma)
484{
485	struct uio_device *idev = vma->vm_private_data;
486	idev->vma_count--;
487}
488
489static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
490{
491	struct uio_device *idev = vma->vm_private_data;
492	struct page *page;
493	unsigned long offset;
494
495	int mi = uio_find_mem_index(vma);
496	if (mi < 0)
497		return VM_FAULT_SIGBUS;
498
499	/*
500	 * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
501	 * to use mem[N].
502	 */
503	offset = (vmf->pgoff - mi) << PAGE_SHIFT;
504
505	if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
506		page = virt_to_page(idev->info->mem[mi].addr + offset);
507	else
508		page = vmalloc_to_page((void *)idev->info->mem[mi].addr
509							+ offset);
510	get_page(page);
511	vmf->page = page;
512	return 0;
513}
514
515static struct vm_operations_struct uio_vm_ops = {
516	.open = uio_vma_open,
517	.close = uio_vma_close,
518	.fault = uio_vma_fault,
519};
520
521static int uio_mmap_physical(struct vm_area_struct *vma)
522{
523	struct uio_device *idev = vma->vm_private_data;
524	int mi = uio_find_mem_index(vma);
525	if (mi < 0)
526		return -EINVAL;
527
528	vma->vm_flags |= VM_IO | VM_RESERVED;
529
530	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
531
532	return remap_pfn_range(vma,
533			       vma->vm_start,
534			       idev->info->mem[mi].addr >> PAGE_SHIFT,
535			       vma->vm_end - vma->vm_start,
536			       vma->vm_page_prot);
537}
538
539static int uio_mmap_logical(struct vm_area_struct *vma)
540{
541	vma->vm_flags |= VM_RESERVED;
542	vma->vm_ops = &uio_vm_ops;
543	uio_vma_open(vma);
544	return 0;
545}
546
547static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
548{
549	struct uio_listener *listener = filep->private_data;
550	struct uio_device *idev = listener->dev;
551	int mi;
552	unsigned long requested_pages, actual_pages;
553	int ret = 0;
554
555	if (vma->vm_end < vma->vm_start)
556		return -EINVAL;
557
558	vma->vm_private_data = idev;
559
560	mi = uio_find_mem_index(vma);
561	if (mi < 0)
562		return -EINVAL;
563
564	requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
565	actual_pages = (idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
566	if (requested_pages > actual_pages)
567		return -EINVAL;
568
569	if (idev->info->mmap) {
570		ret = idev->info->mmap(idev->info, vma);
571		return ret;
572	}
573
574	switch (idev->info->mem[mi].memtype) {
575		case UIO_MEM_PHYS:
576			return uio_mmap_physical(vma);
577		case UIO_MEM_LOGICAL:
578		case UIO_MEM_VIRTUAL:
579			return uio_mmap_logical(vma);
580		default:
581			return -EINVAL;
582	}
583}
584
585static const struct file_operations uio_fops = {
586	.owner		= THIS_MODULE,
587	.open		= uio_open,
588	.release	= uio_release,
589	.read		= uio_read,
590	.write		= uio_write,
591	.mmap		= uio_mmap,
592	.poll		= uio_poll,
593	.fasync		= uio_fasync,
594};
595
596static int uio_major_init(void)
597{
598	uio_major = register_chrdev(0, "uio", &uio_fops);
599	if (uio_major < 0)
600		return uio_major;
601	return 0;
602}
603
604static void uio_major_cleanup(void)
605{
606	unregister_chrdev(uio_major, "uio");
607}
608
609static int init_uio_class(void)
610{
611	int ret = 0;
612
613	if (uio_class != NULL) {
614		kref_get(&uio_class->kref);
615		goto exit;
616	}
617
618	/* This is the first time in here, set everything up properly */
619	ret = uio_major_init();
620	if (ret)
621		goto exit;
622
623	uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
624	if (!uio_class) {
625		ret = -ENOMEM;
626		goto err_kzalloc;
627	}
628
629	kref_init(&uio_class->kref);
630	uio_class->class = class_create(THIS_MODULE, "uio");
631	if (IS_ERR(uio_class->class)) {
632		ret = IS_ERR(uio_class->class);
633		printk(KERN_ERR "class_create failed for uio\n");
634		goto err_class_create;
635	}
636	return 0;
637
638err_class_create:
639	kfree(uio_class);
640	uio_class = NULL;
641err_kzalloc:
642	uio_major_cleanup();
643exit:
644	return ret;
645}
646
647static void release_uio_class(struct kref *kref)
648{
649	/* Ok, we cheat as we know we only have one uio_class */
650	class_destroy(uio_class->class);
651	kfree(uio_class);
652	uio_major_cleanup();
653	uio_class = NULL;
654}
655
656static void uio_class_destroy(void)
657{
658	if (uio_class)
659		kref_put(&uio_class->kref, release_uio_class);
660}
661
662/**
663 * uio_register_device - register a new userspace IO device
664 * @owner:	module that creates the new device
665 * @parent:	parent device
666 * @info:	UIO device capabilities
667 *
668 * returns zero on success or a negative error code.
669 */
670int __uio_register_device(struct module *owner,
671			  struct device *parent,
672			  struct uio_info *info)
673{
674	struct uio_device *idev;
675	int ret = 0;
676
677	if (!parent || !info || !info->name || !info->version)
678		return -EINVAL;
679
680	info->uio_dev = NULL;
681
682	ret = init_uio_class();
683	if (ret)
684		return ret;
685
686	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
687	if (!idev) {
688		ret = -ENOMEM;
689		goto err_kzalloc;
690	}
691
692	idev->owner = owner;
693	idev->info = info;
694	init_waitqueue_head(&idev->wait);
695	atomic_set(&idev->event, 0);
696
697	ret = uio_get_minor(idev);
698	if (ret)
699		goto err_get_minor;
700
701	idev->dev = device_create(uio_class->class, parent,
702				  MKDEV(uio_major, idev->minor), idev,
703				  "uio%d", idev->minor);
704	if (IS_ERR(idev->dev)) {
705		printk(KERN_ERR "UIO: device register failed\n");
706		ret = PTR_ERR(idev->dev);
707		goto err_device_create;
708	}
709
710	ret = uio_dev_add_attributes(idev);
711	if (ret)
712		goto err_uio_dev_add_attributes;
713
714	info->uio_dev = idev;
715
716	if (idev->info->irq >= 0) {
717		ret = request_irq(idev->info->irq, uio_interrupt,
718				  idev->info->irq_flags, idev->info->name, idev);
719		if (ret)
720			goto err_request_irq;
721	}
722
723	return 0;
724
725err_request_irq:
726	uio_dev_del_attributes(idev);
727err_uio_dev_add_attributes:
728	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
729err_device_create:
730	uio_free_minor(idev);
731err_get_minor:
732	kfree(idev);
733err_kzalloc:
734	uio_class_destroy();
735	return ret;
736}
737EXPORT_SYMBOL_GPL(__uio_register_device);
738
739/**
740 * uio_unregister_device - unregister a industrial IO device
741 * @info:	UIO device capabilities
742 *
743 */
744void uio_unregister_device(struct uio_info *info)
745{
746	struct uio_device *idev;
747
748	if (!info || !info->uio_dev)
749		return;
750
751	idev = info->uio_dev;
752
753	uio_free_minor(idev);
754
755	if (info->irq >= 0)
756		free_irq(info->irq, idev);
757
758	uio_dev_del_attributes(idev);
759
760	dev_set_drvdata(idev->dev, NULL);
761	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
762	kfree(idev);
763	uio_class_destroy();
764
765	return;
766}
767EXPORT_SYMBOL_GPL(uio_unregister_device);
768
769static int __init uio_init(void)
770{
771	return 0;
772}
773
774static void __exit uio_exit(void)
775{
776}
777
778module_init(uio_init)
779module_exit(uio_exit)
780MODULE_LICENSE("GPL v2");
781