]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/ofed/include/linux/linux_compat.c
MFC r276749:
[FreeBSD/stable/10.git] / sys / ofed / include / linux / linux_compat.c
1 /*-
2  * Copyright (c) 2010 Isilon Systems, Inc.
3  * Copyright (c) 2010 iX Systems, Inc.
4  * Copyright (c) 2010 Panasas, Inc.
5  * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice unmodified, this list of conditions, and the following
13  *    disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/kernel.h>
34 #include <sys/sysctl.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/bus.h>
38 #include <sys/fcntl.h>
39 #include <sys/file.h>
40 #include <sys/filio.h>
41 #include <sys/rwlock.h>
42
43 #include <vm/vm.h>
44 #include <vm/pmap.h>
45
46 #include <machine/stdarg.h>
47 #include <machine/pmap.h>
48
49 #include <linux/kobject.h>
50 #include <linux/device.h>
51 #include <linux/slab.h>
52 #include <linux/module.h>
53 #include <linux/cdev.h>
54 #include <linux/file.h>
55 #include <linux/sysfs.h>
56 #include <linux/mm.h>
57 #include <linux/io.h>
58 #include <linux/vmalloc.h>
59
60 #include <vm/vm_pager.h>
61
62 MALLOC_DEFINE(M_KMALLOC, "linux", "Linux kmalloc compat");
63
64 #include <linux/rbtree.h>
65 /* Undo Linux compat changes. */
66 #undef RB_ROOT
67 #undef file
68 #undef cdev
69 #define RB_ROOT(head)   (head)->rbh_root
70 #undef LIST_HEAD
71 /* From sys/queue.h */
72 #define LIST_HEAD(name, type)                                           \
73 struct name {                                                           \
74         struct type *lh_first;  /* first element */                     \
75 }
76
77 struct kobject class_root;
78 struct device linux_rootdev;
79 struct class miscclass;
80 struct list_head pci_drivers;
81 struct list_head pci_devices;
82 spinlock_t pci_lock;
83
84 int
85 panic_cmp(struct rb_node *one, struct rb_node *two)
86 {
87         panic("no cmp");
88 }
89
90 RB_GENERATE(linux_root, rb_node, __entry, panic_cmp);
91  
92 int
93 kobject_set_name(struct kobject *kobj, const char *fmt, ...)
94 {
95         va_list args;
96         int error;
97
98         va_start(args, fmt);
99         error = kobject_set_name_vargs(kobj, fmt, args);
100         va_end(args);
101
102         return (error);
103 }
104
105 static inline int
106 kobject_add_complete(struct kobject *kobj, struct kobject *parent)
107 {
108         struct kobj_type *t;
109         int error;
110
111         kobj->parent = kobject_get(parent);
112         error = sysfs_create_dir(kobj);
113         if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) {
114                 struct attribute **attr;
115                 t = kobj->ktype;
116
117                 for (attr = t->default_attrs; *attr != NULL; attr++) {
118                         error = sysfs_create_file(kobj, *attr);
119                         if (error)
120                                 break;
121                 }
122                 if (error)
123                         sysfs_remove_dir(kobj);
124                 
125         }
126         return (error);
127 }
128
129 int
130 kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...)
131 {
132         va_list args;
133         int error;
134
135         va_start(args, fmt);
136         error = kobject_set_name_vargs(kobj, fmt, args);
137         va_end(args);
138         if (error)
139                 return (error);
140
141         return kobject_add_complete(kobj, parent);
142 }
143
144 void
145 kobject_release(struct kref *kref)
146 {
147         struct kobject *kobj;
148         char *name;
149
150         kobj = container_of(kref, struct kobject, kref);
151         sysfs_remove_dir(kobj);
152         if (kobj->parent)
153                 kobject_put(kobj->parent);
154         kobj->parent = NULL;
155         name = kobj->name;
156         if (kobj->ktype && kobj->ktype->release)
157                 kobj->ktype->release(kobj);
158         kfree(name);
159 }
160
161 static void
162 kobject_kfree(struct kobject *kobj)
163 {
164         kfree(kobj);
165 }
166
167 static void
168 kobject_kfree_name(struct kobject *kobj)
169 {
170         if (kobj) {
171                 kfree(kobj->name);
172         }
173 }
174
175 struct kobj_type kfree_type = { .release = kobject_kfree };
176
177 static void
178 dev_release(struct device *dev)
179 {
180         pr_debug("dev_release: %s\n", dev_name(dev));
181         kfree(dev);
182 }
183
184 struct device *
185 device_create(struct class *class, struct device *parent, dev_t devt,
186     void *drvdata, const char *fmt, ...)
187 {
188         struct device *dev;
189         va_list args;
190
191         dev = kzalloc(sizeof(*dev), M_WAITOK);
192         dev->parent = parent;
193         dev->class = class;
194         dev->devt = devt;
195         dev->driver_data = drvdata;
196         dev->release = dev_release;
197         va_start(args, fmt);
198         kobject_set_name_vargs(&dev->kobj, fmt, args);
199         va_end(args);
200         device_register(dev);
201
202         return (dev);
203 }
204
205 int
206 kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
207     struct kobject *parent, const char *fmt, ...)
208 {
209         va_list args;
210         int error;
211
212         kobject_init(kobj, ktype);
213         kobj->ktype = ktype;
214         kobj->parent = parent;
215         kobj->name = NULL;
216
217         va_start(args, fmt);
218         error = kobject_set_name_vargs(kobj, fmt, args);
219         va_end(args);
220         if (error)
221                 return (error);
222         return kobject_add_complete(kobj, parent);
223 }
224
225 static void
226 linux_file_dtor(void *cdp)
227 {
228         struct linux_file *filp;
229
230         filp = cdp;
231         filp->f_op->release(filp->f_vnode, filp);
232         vdrop(filp->f_vnode);
233         kfree(filp);
234 }
235
236 static int
237 linux_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
238 {
239         struct linux_cdev *ldev;
240         struct linux_file *filp;
241         struct file *file;
242         int error;
243
244         file = curthread->td_fpop;
245         ldev = dev->si_drv1;
246         if (ldev == NULL)
247                 return (ENODEV);
248         filp = kzalloc(sizeof(*filp), GFP_KERNEL);
249         filp->f_dentry = &filp->f_dentry_store;
250         filp->f_op = ldev->ops;
251         filp->f_flags = file->f_flag;
252         vhold(file->f_vnode);
253         filp->f_vnode = file->f_vnode;
254         if (filp->f_op->open) {
255                 error = -filp->f_op->open(file->f_vnode, filp);
256                 if (error) {
257                         kfree(filp);
258                         return (error);
259                 }
260         }
261         error = devfs_set_cdevpriv(filp, linux_file_dtor);
262         if (error) {
263                 filp->f_op->release(file->f_vnode, filp);
264                 kfree(filp);
265                 return (error);
266         }
267
268         return 0;
269 }
270
271 static int
272 linux_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
273 {
274         struct linux_cdev *ldev;
275         struct linux_file *filp;
276         struct file *file;
277         int error;
278
279         file = curthread->td_fpop;
280         ldev = dev->si_drv1;
281         if (ldev == NULL)
282                 return (0);
283         if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
284                 return (error);
285         filp->f_flags = file->f_flag;
286         devfs_clear_cdevpriv();
287         
288
289         return (0);
290 }
291
292 static int
293 linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
294     struct thread *td)
295 {
296         struct linux_cdev *ldev;
297         struct linux_file *filp;
298         struct file *file;
299         int error;
300
301         file = curthread->td_fpop;
302         ldev = dev->si_drv1;
303         if (ldev == NULL)
304                 return (0);
305         if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
306                 return (error);
307         filp->f_flags = file->f_flag;
308         /*
309          * Linux does not have a generic ioctl copyin/copyout layer.  All
310          * linux ioctls must be converted to void ioctls which pass a
311          * pointer to the address of the data.  We want the actual user
312          * address so we dereference here.
313          */
314         data = *(void **)data;
315         if (filp->f_op->unlocked_ioctl)
316                 error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data);
317         else
318                 error = ENOTTY;
319
320         return (error);
321 }
322
323 static int
324 linux_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
325 {
326         struct linux_cdev *ldev;
327         struct linux_file *filp;
328         struct file *file;
329         ssize_t bytes;
330         int error;
331
332         file = curthread->td_fpop;
333         ldev = dev->si_drv1;
334         if (ldev == NULL)
335                 return (0);
336         if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
337                 return (error);
338         filp->f_flags = file->f_flag;
339         if (uio->uio_iovcnt != 1)
340                 panic("linux_dev_read: uio %p iovcnt %d",
341                     uio, uio->uio_iovcnt);
342         if (filp->f_op->read) {
343                 bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
344                     uio->uio_iov->iov_len, &uio->uio_offset);
345                 if (bytes >= 0) {
346                         uio->uio_iov->iov_base += bytes;
347                         uio->uio_iov->iov_len -= bytes;
348                         uio->uio_resid -= bytes;
349                 } else
350                         error = -bytes;
351         } else
352                 error = ENXIO;
353
354         return (error);
355 }
356
357 static int
358 linux_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
359 {
360         struct linux_cdev *ldev;
361         struct linux_file *filp;
362         struct file *file;
363         ssize_t bytes;
364         int error;
365
366         file = curthread->td_fpop;
367         ldev = dev->si_drv1;
368         if (ldev == NULL)
369                 return (0);
370         if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
371                 return (error);
372         filp->f_flags = file->f_flag;
373         if (uio->uio_iovcnt != 1)
374                 panic("linux_dev_write: uio %p iovcnt %d",
375                     uio, uio->uio_iovcnt);
376         if (filp->f_op->write) {
377                 bytes = filp->f_op->write(filp, uio->uio_iov->iov_base,
378                     uio->uio_iov->iov_len, &uio->uio_offset);
379                 if (bytes >= 0) {
380                         uio->uio_iov->iov_base += bytes;
381                         uio->uio_iov->iov_len -= bytes;
382                         uio->uio_resid -= bytes;
383                 } else
384                         error = -bytes;
385         } else
386                 error = ENXIO;
387
388         return (error);
389 }
390
391 static int
392 linux_dev_poll(struct cdev *dev, int events, struct thread *td)
393 {
394         struct linux_cdev *ldev;
395         struct linux_file *filp;
396         struct file *file;
397         int revents;
398         int error;
399
400         file = curthread->td_fpop;
401         ldev = dev->si_drv1;
402         if (ldev == NULL)
403                 return (0);
404         if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
405                 return (error);
406         filp->f_flags = file->f_flag;
407         if (filp->f_op->poll)
408                 revents = filp->f_op->poll(filp, NULL) & events;
409         else
410                 revents = 0;
411
412         return (revents);
413 }
414
415 static int
416 linux_dev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
417     int nprot, vm_memattr_t *memattr)
418 {
419
420         /* XXX memattr not honored. */
421         *paddr = offset;
422         return (0);
423 }
424
425 static int
426 linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
427     vm_size_t size, struct vm_object **object, int nprot)
428 {
429         struct linux_cdev *ldev;
430         struct linux_file *filp;
431         struct file *file;
432         struct vm_area_struct vma;
433         vm_paddr_t paddr;
434         vm_page_t m;
435         int error;
436
437         file = curthread->td_fpop;
438         ldev = dev->si_drv1;
439         if (ldev == NULL)
440                 return (ENODEV);
441         if (size != PAGE_SIZE)
442                 return (EINVAL);
443         if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
444                 return (error);
445         filp->f_flags = file->f_flag;
446         vma.vm_start = 0;
447         vma.vm_end = PAGE_SIZE;
448         vma.vm_pgoff = *offset / PAGE_SIZE;
449         vma.vm_pfn = 0;
450         vma.vm_page_prot = 0;
451         if (filp->f_op->mmap) {
452                 error = -filp->f_op->mmap(filp, &vma);
453                 if (error == 0) {
454                         paddr = (vm_paddr_t)vma.vm_pfn << PAGE_SHIFT;
455                         *offset = paddr;
456                         m = PHYS_TO_VM_PAGE(paddr);
457                         *object = vm_pager_allocate(OBJT_DEVICE, dev,
458                             PAGE_SIZE, nprot, *offset, curthread->td_ucred);
459                         if (*object == NULL)
460                                  return (EINVAL);
461                         if (vma.vm_page_prot != VM_MEMATTR_DEFAULT)
462                                 pmap_page_set_memattr(m, vma.vm_page_prot);
463                 }
464         } else
465                 error = ENODEV;
466
467         return (error);
468 }
469
470 struct cdevsw linuxcdevsw = {
471         .d_version = D_VERSION,
472         .d_flags = D_TRACKCLOSE,
473         .d_open = linux_dev_open,
474         .d_close = linux_dev_close,
475         .d_read = linux_dev_read,
476         .d_write = linux_dev_write,
477         .d_ioctl = linux_dev_ioctl,
478         .d_mmap_single = linux_dev_mmap_single,
479         .d_mmap = linux_dev_mmap,
480         .d_poll = linux_dev_poll,
481 };
482
483 static int
484 linux_file_read(struct file *file, struct uio *uio, struct ucred *active_cred,
485     int flags, struct thread *td)
486 {
487         struct linux_file *filp;
488         ssize_t bytes;
489         int error;
490
491         error = 0;
492         filp = (struct linux_file *)file->f_data;
493         filp->f_flags = file->f_flag;
494         if (uio->uio_iovcnt != 1)
495                 panic("linux_file_read: uio %p iovcnt %d",
496                     uio, uio->uio_iovcnt);
497         if (filp->f_op->read) {
498                 bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
499                     uio->uio_iov->iov_len, &uio->uio_offset);
500                 if (bytes >= 0) {
501                         uio->uio_iov->iov_base += bytes;
502                         uio->uio_iov->iov_len -= bytes;
503                         uio->uio_resid -= bytes;
504                 } else
505                         error = -bytes;
506         } else
507                 error = ENXIO;
508
509         return (error);
510 }
511
512 static int
513 linux_file_poll(struct file *file, int events, struct ucred *active_cred,
514     struct thread *td)
515 {
516         struct linux_file *filp;
517         int revents;
518
519         filp = (struct linux_file *)file->f_data;
520         filp->f_flags = file->f_flag;
521         if (filp->f_op->poll)
522                 revents = filp->f_op->poll(filp, NULL) & events;
523         else
524                 revents = 0;
525
526         return (0);
527 }
528
529 static int
530 linux_file_close(struct file *file, struct thread *td)
531 {
532         struct linux_file *filp;
533         int error;
534
535         filp = (struct linux_file *)file->f_data;
536         filp->f_flags = file->f_flag;
537         error = -filp->f_op->release(NULL, filp);
538         funsetown(&filp->f_sigio);
539         kfree(filp);
540
541         return (error);
542 }
543
544 static int
545 linux_file_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *cred,
546     struct thread *td)
547 {
548         struct linux_file *filp;
549         int error;
550
551         filp = (struct linux_file *)fp->f_data;
552         filp->f_flags = fp->f_flag;
553         error = 0;
554
555         switch (cmd) {
556         case FIONBIO:
557                 break;
558         case FIOASYNC:
559                 if (filp->f_op->fasync == NULL)
560                         break;
561                 error = filp->f_op->fasync(0, filp, fp->f_flag & FASYNC);
562                 break;
563         case FIOSETOWN:
564                 error = fsetown(*(int *)data, &filp->f_sigio);
565                 if (error == 0)
566                         error = filp->f_op->fasync(0, filp,
567                             fp->f_flag & FASYNC);
568                 break;
569         case FIOGETOWN:
570                 *(int *)data = fgetown(&filp->f_sigio);
571                 break;
572         default:
573                 error = ENOTTY;
574                 break;
575         }
576         return (error);
577 }
578
579 struct fileops linuxfileops = {
580         .fo_read = linux_file_read,
581         .fo_poll = linux_file_poll,
582         .fo_close = linux_file_close,
583         .fo_ioctl = linux_file_ioctl,
584         .fo_chmod = invfo_chmod,
585         .fo_chown = invfo_chown,
586         .fo_sendfile = invfo_sendfile,
587 };
588
589 /*
590  * Hash of vmmap addresses.  This is infrequently accessed and does not
591  * need to be particularly large.  This is done because we must store the
592  * caller's idea of the map size to properly unmap.
593  */
594 struct vmmap {
595         LIST_ENTRY(vmmap)       vm_next;
596         void                    *vm_addr;
597         unsigned long           vm_size;
598 };
599
600 LIST_HEAD(vmmaphd, vmmap);
601 #define VMMAP_HASH_SIZE 64
602 #define VMMAP_HASH_MASK (VMMAP_HASH_SIZE - 1)
603 #define VM_HASH(addr)   ((uintptr_t)(addr) >> PAGE_SHIFT) & VMMAP_HASH_MASK
604 static struct vmmaphd vmmaphead[VMMAP_HASH_SIZE];
605 static struct mtx vmmaplock;
606
607 static void
608 vmmap_add(void *addr, unsigned long size)
609 {
610         struct vmmap *vmmap;
611
612         vmmap = kmalloc(sizeof(*vmmap), GFP_KERNEL);
613         mtx_lock(&vmmaplock);
614         vmmap->vm_size = size;
615         vmmap->vm_addr = addr;
616         LIST_INSERT_HEAD(&vmmaphead[VM_HASH(addr)], vmmap, vm_next);
617         mtx_unlock(&vmmaplock);
618 }
619
620 static struct vmmap *
621 vmmap_remove(void *addr)
622 {
623         struct vmmap *vmmap;
624
625         mtx_lock(&vmmaplock);
626         LIST_FOREACH(vmmap, &vmmaphead[VM_HASH(addr)], vm_next)
627                 if (vmmap->vm_addr == addr)
628                         break;
629         if (vmmap)
630                 LIST_REMOVE(vmmap, vm_next);
631         mtx_unlock(&vmmaplock);
632
633         return (vmmap);
634 }
635
636 void *
637 _ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr)
638 {
639         void *addr;
640
641         addr = pmap_mapdev_attr(phys_addr, size, attr);
642         if (addr == NULL)
643                 return (NULL);
644         vmmap_add(addr, size);
645
646         return (addr);
647 }
648
649 void
650 iounmap(void *addr)
651 {
652         struct vmmap *vmmap;
653
654         vmmap = vmmap_remove(addr);
655         if (vmmap == NULL)
656                 return;
657         pmap_unmapdev((vm_offset_t)addr, vmmap->vm_size);
658         kfree(vmmap);
659 }
660
661
662 void *
663 vmap(struct page **pages, unsigned int count, unsigned long flags, int prot)
664 {
665         vm_offset_t off;
666         size_t size;
667
668         size = count * PAGE_SIZE;
669         off = kva_alloc(size);
670         if (off == 0)
671                 return (NULL);
672         vmmap_add((void *)off, size);
673         pmap_qenter(off, pages, count);
674
675         return ((void *)off);
676 }
677
678 void
679 vunmap(void *addr)
680 {
681         struct vmmap *vmmap;
682
683         vmmap = vmmap_remove(addr);
684         if (vmmap == NULL)
685                 return;
686         pmap_qremove((vm_offset_t)addr, vmmap->vm_size / PAGE_SIZE);
687         kva_free((vm_offset_t)addr, vmmap->vm_size);
688         kfree(vmmap);
689 }
690
691 static void
692 linux_compat_init(void)
693 {
694         struct sysctl_oid *rootoid;
695         int i;
696
697         rootoid = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(),
698             OID_AUTO, "sys", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "sys");
699         kobject_init(&class_root, &class_ktype);
700         kobject_set_name(&class_root, "class");
701         class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid),
702             OID_AUTO, "class", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "class");
703         kobject_init(&linux_rootdev.kobj, &dev_ktype);
704         kobject_set_name(&linux_rootdev.kobj, "device");
705         linux_rootdev.kobj.oidp = SYSCTL_ADD_NODE(NULL,
706             SYSCTL_CHILDREN(rootoid), OID_AUTO, "device", CTLFLAG_RD, NULL,
707             "device");
708         linux_rootdev.bsddev = root_bus;
709         miscclass.name = "misc";
710         class_register(&miscclass);
711         INIT_LIST_HEAD(&pci_drivers);
712         INIT_LIST_HEAD(&pci_devices);
713         spin_lock_init(&pci_lock);
714         mtx_init(&vmmaplock, "IO Map lock", NULL, MTX_DEF);
715         for (i = 0; i < VMMAP_HASH_SIZE; i++)
716                 LIST_INIT(&vmmaphead[i]);
717 }
718
719 SYSINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_init, NULL);
720
721 static void
722 linux_compat_uninit(void)
723 {
724         kobject_kfree_name(&class_root);
725         kobject_kfree_name(&linux_rootdev.kobj);
726         kobject_kfree_name(&miscclass.kobj);
727 }
728 SYSUNINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_uninit, NULL);