linux/drivers/uio/uio.c
<<
>>
Prefs
   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        struct kobject          *portio_dir;
  39};
  40
  41static int uio_major;
  42static DEFINE_IDR(uio_idr);
  43static const struct file_operations uio_fops;
  44
  45/* UIO class infrastructure */
  46static struct uio_class {
  47        struct kref kref;
  48        struct class *class;
  49} *uio_class;
  50
  51/* Protect idr accesses */
  52static DEFINE_MUTEX(minor_lock);
  53
  54/*
  55 * attributes
  56 */
  57
  58struct uio_map {
  59        struct kobject kobj;
  60        struct uio_mem *mem;
  61};
  62#define to_map(map) container_of(map, struct uio_map, kobj)
  63
  64static ssize_t map_name_show(struct uio_mem *mem, char *buf)
  65{
  66        if (unlikely(!mem->name))
  67                mem->name = "";
  68
  69        return sprintf(buf, "%s\n", mem->name);
  70}
  71
  72static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
  73{
  74        return sprintf(buf, "0x%lx\n", mem->addr);
  75}
  76
  77static ssize_t map_size_show(struct uio_mem *mem, char *buf)
  78{
  79        return sprintf(buf, "0x%lx\n", mem->size);
  80}
  81
  82static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
  83{
  84        return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
  85}
  86
  87struct map_sysfs_entry {
  88        struct attribute attr;
  89        ssize_t (*show)(struct uio_mem *, char *);
  90        ssize_t (*store)(struct uio_mem *, const char *, size_t);
  91};
  92
  93static struct map_sysfs_entry name_attribute =
  94        __ATTR(name, S_IRUGO, map_name_show, NULL);
  95static struct map_sysfs_entry addr_attribute =
  96        __ATTR(addr, S_IRUGO, map_addr_show, NULL);
  97static struct map_sysfs_entry size_attribute =
  98        __ATTR(size, S_IRUGO, map_size_show, NULL);
  99static struct map_sysfs_entry offset_attribute =
 100        __ATTR(offset, S_IRUGO, map_offset_show, NULL);
 101
 102static struct attribute *attrs[] = {
 103        &name_attribute.attr,
 104        &addr_attribute.attr,
 105        &size_attribute.attr,
 106        &offset_attribute.attr,
 107        NULL,   /* need to NULL terminate the list of attributes */
 108};
 109
 110static void map_release(struct kobject *kobj)
 111{
 112        struct uio_map *map = to_map(kobj);
 113        kfree(map);
 114}
 115
 116static ssize_t map_type_show(struct kobject *kobj, struct attribute *attr,
 117                             char *buf)
 118{
 119        struct uio_map *map = to_map(kobj);
 120        struct uio_mem *mem = map->mem;
 121        struct map_sysfs_entry *entry;
 122
 123        entry = container_of(attr, struct map_sysfs_entry, attr);
 124
 125        if (!entry->show)
 126                return -EIO;
 127
 128        return entry->show(mem, buf);
 129}
 130
 131static struct sysfs_ops map_sysfs_ops = {
 132        .show = map_type_show,
 133};
 134
 135static struct kobj_type map_attr_type = {
 136        .release        = map_release,
 137        .sysfs_ops      = &map_sysfs_ops,
 138        .default_attrs  = attrs,
 139};
 140
 141struct uio_portio {
 142        struct kobject kobj;
 143        struct uio_port *port;
 144};
 145#define to_portio(portio) container_of(portio, struct uio_portio, kobj)
 146
 147static ssize_t portio_name_show(struct uio_port *port, char *buf)
 148{
 149        if (unlikely(!port->name))
 150                port->name = "";
 151
 152        return sprintf(buf, "%s\n", port->name);
 153}
 154
 155static ssize_t portio_start_show(struct uio_port *port, char *buf)
 156{
 157        return sprintf(buf, "0x%lx\n", port->start);
 158}
 159
 160static ssize_t portio_size_show(struct uio_port *port, char *buf)
 161{
 162        return sprintf(buf, "0x%lx\n", port->size);
 163}
 164
 165static ssize_t portio_porttype_show(struct uio_port *port, char *buf)
 166{
 167        const char *porttypes[] = {"none", "x86", "gpio", "other"};
 168
 169        if ((port->porttype < 0) || (port->porttype > UIO_PORT_OTHER))
 170                return -EINVAL;
 171
 172        return sprintf(buf, "port_%s\n", porttypes[port->porttype]);
 173}
 174
 175struct portio_sysfs_entry {
 176        struct attribute attr;
 177        ssize_t (*show)(struct uio_port *, char *);
 178        ssize_t (*store)(struct uio_port *, const char *, size_t);
 179};
 180
 181static struct portio_sysfs_entry portio_name_attribute =
 182        __ATTR(name, S_IRUGO, portio_name_show, NULL);
 183static struct portio_sysfs_entry portio_start_attribute =
 184        __ATTR(start, S_IRUGO, portio_start_show, NULL);
 185static struct portio_sysfs_entry portio_size_attribute =
 186        __ATTR(size, S_IRUGO, portio_size_show, NULL);
 187static struct portio_sysfs_entry portio_porttype_attribute =
 188        __ATTR(porttype, S_IRUGO, portio_porttype_show, NULL);
 189
 190static struct attribute *portio_attrs[] = {
 191        &portio_name_attribute.attr,
 192        &portio_start_attribute.attr,
 193        &portio_size_attribute.attr,
 194        &portio_porttype_attribute.attr,
 195        NULL,
 196};
 197
 198static void portio_release(struct kobject *kobj)
 199{
 200        struct uio_portio *portio = to_portio(kobj);
 201        kfree(portio);
 202}
 203
 204static ssize_t portio_type_show(struct kobject *kobj, struct attribute *attr,
 205                             char *buf)
 206{
 207        struct uio_portio *portio = to_portio(kobj);
 208        struct uio_port *port = portio->port;
 209        struct portio_sysfs_entry *entry;
 210
 211        entry = container_of(attr, struct portio_sysfs_entry, attr);
 212
 213        if (!entry->show)
 214                return -EIO;
 215
 216        return entry->show(port, buf);
 217}
 218
 219static struct sysfs_ops portio_sysfs_ops = {
 220        .show = portio_type_show,
 221};
 222
 223static struct kobj_type portio_attr_type = {
 224        .release        = portio_release,
 225        .sysfs_ops      = &portio_sysfs_ops,
 226        .default_attrs  = portio_attrs,
 227};
 228
 229static ssize_t show_name(struct device *dev,
 230                         struct device_attribute *attr, char *buf)
 231{
 232        struct uio_device *idev = dev_get_drvdata(dev);
 233        if (idev)
 234                return sprintf(buf, "%s\n", idev->info->name);
 235        else
 236                return -ENODEV;
 237}
 238static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 239
 240static ssize_t show_version(struct device *dev,
 241                            struct device_attribute *attr, char *buf)
 242{
 243        struct uio_device *idev = dev_get_drvdata(dev);
 244        if (idev)
 245                return sprintf(buf, "%s\n", idev->info->version);
 246        else
 247                return -ENODEV;
 248}
 249static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 250
 251static ssize_t show_event(struct device *dev,
 252                          struct device_attribute *attr, char *buf)
 253{
 254        struct uio_device *idev = dev_get_drvdata(dev);
 255        if (idev)
 256                return sprintf(buf, "%u\n",
 257                                (unsigned int)atomic_read(&idev->event));
 258        else
 259                return -ENODEV;
 260}
 261static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
 262
 263static struct attribute *uio_attrs[] = {
 264        &dev_attr_name.attr,
 265        &dev_attr_version.attr,
 266        &dev_attr_event.attr,
 267        NULL,
 268};
 269
 270static struct attribute_group uio_attr_grp = {
 271        .attrs = uio_attrs,
 272};
 273
 274/*
 275 * device functions
 276 */
 277static int uio_dev_add_attributes(struct uio_device *idev)
 278{
 279        int ret;
 280        int mi, pi;
 281        int map_found = 0;
 282        int portio_found = 0;
 283        struct uio_mem *mem;
 284        struct uio_map *map;
 285        struct uio_port *port;
 286        struct uio_portio *portio;
 287
 288        ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
 289        if (ret)
 290                goto err_group;
 291
 292        for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
 293                mem = &idev->info->mem[mi];
 294                if (mem->size == 0)
 295                        break;
 296                if (!map_found) {
 297                        map_found = 1;
 298                        idev->map_dir = kobject_create_and_add("maps",
 299                                                        &idev->dev->kobj);
 300                        if (!idev->map_dir)
 301                                goto err_map;
 302                }
 303                map = kzalloc(sizeof(*map), GFP_KERNEL);
 304                if (!map)
 305                        goto err_map;
 306                kobject_init(&map->kobj, &map_attr_type);
 307                map->mem = mem;
 308                mem->map = map;
 309                ret = kobject_add(&map->kobj, idev->map_dir, "map%d", mi);
 310                if (ret)
 311                        goto err_map;
 312                ret = kobject_uevent(&map->kobj, KOBJ_ADD);
 313                if (ret)
 314                        goto err_map;
 315        }
 316
 317        for (pi = 0; pi < MAX_UIO_PORT_REGIONS; pi++) {
 318                port = &idev->info->port[pi];
 319                if (port->size == 0)
 320                        break;
 321                if (!portio_found) {
 322                        portio_found = 1;
 323                        idev->portio_dir = kobject_create_and_add("portio",
 324                                                        &idev->dev->kobj);
 325                        if (!idev->portio_dir)
 326                                goto err_portio;
 327                }
 328                portio = kzalloc(sizeof(*portio), GFP_KERNEL);
 329                if (!portio)
 330                        goto err_portio;
 331                kobject_init(&portio->kobj, &portio_attr_type);
 332                portio->port = port;
 333                port->portio = portio;
 334                ret = kobject_add(&portio->kobj, idev->portio_dir,
 335                                                        "port%d", pi);
 336                if (ret)
 337                        goto err_portio;
 338                ret = kobject_uevent(&portio->kobj, KOBJ_ADD);
 339                if (ret)
 340                        goto err_portio;
 341        }
 342
 343        return 0;
 344
 345err_portio:
 346        for (pi--; pi >= 0; pi--) {
 347                port = &idev->info->port[pi];
 348                portio = port->portio;
 349                kobject_put(&portio->kobj);
 350        }
 351        kobject_put(idev->portio_dir);
 352err_map:
 353        for (mi--; mi>=0; mi--) {
 354                mem = &idev->info->mem[mi];
 355                map = mem->map;
 356                kobject_put(&map->kobj);
 357        }
 358        kobject_put(idev->map_dir);
 359        sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
 360err_group:
 361        dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
 362        return ret;
 363}
 364
 365static void uio_dev_del_attributes(struct uio_device *idev)
 366{
 367        int i;
 368        struct uio_mem *mem;
 369        struct uio_port *port;
 370
 371        for (i = 0; i < MAX_UIO_MAPS; i++) {
 372                mem = &idev->info->mem[i];
 373                if (mem->size == 0)
 374                        break;
 375                kobject_put(&mem->map->kobj);
 376        }
 377        kobject_put(idev->map_dir);
 378
 379        for (i = 0; i < MAX_UIO_PORT_REGIONS; i++) {
 380                port = &idev->info->port[i];
 381                if (port->size == 0)
 382                        break;
 383                kobject_put(&port->portio->kobj);
 384        }
 385        kobject_put(idev->portio_dir);
 386
 387        sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
 388}
 389
 390static int uio_get_minor(struct uio_device *idev)
 391{
 392        int retval = -ENOMEM;
 393        int id;
 394
 395        mutex_lock(&minor_lock);
 396        if (idr_pre_get(&uio_idr, GFP_KERNEL) == 0)
 397                goto exit;
 398
 399        retval = idr_get_new(&uio_idr, idev, &id);
 400        if (retval < 0) {
 401                if (retval == -EAGAIN)
 402                        retval = -ENOMEM;
 403                goto exit;
 404        }
 405        idev->minor = id & MAX_ID_MASK;
 406exit:
 407        mutex_unlock(&minor_lock);
 408        return retval;
 409}
 410
 411static void uio_free_minor(struct uio_device *idev)
 412{
 413        mutex_lock(&minor_lock);
 414        idr_remove(&uio_idr, idev->minor);
 415        mutex_unlock(&minor_lock);
 416}
 417
 418/**
 419 * uio_event_notify - trigger an interrupt event
 420 * @info: UIO device capabilities
 421 */
 422void uio_event_notify(struct uio_info *info)
 423{
 424        struct uio_device *idev = info->uio_dev;
 425
 426        atomic_inc(&idev->event);
 427        wake_up_interruptible(&idev->wait);
 428        kill_fasync(&idev->async_queue, SIGIO, POLL_IN);
 429}
 430EXPORT_SYMBOL_GPL(uio_event_notify);
 431
 432/**
 433 * uio_interrupt - hardware interrupt handler
 434 * @irq: IRQ number, can be UIO_IRQ_CYCLIC for cyclic timer
 435 * @dev_id: Pointer to the devices uio_device structure
 436 */
 437static irqreturn_t uio_interrupt(int irq, void *dev_id)
 438{
 439        struct uio_device *idev = (struct uio_device *)dev_id;
 440        irqreturn_t ret = idev->info->handler(irq, idev->info);
 441
 442        if (ret == IRQ_HANDLED)
 443                uio_event_notify(idev->info);
 444
 445        return ret;
 446}
 447
 448struct uio_listener {
 449        struct uio_device *dev;
 450        s32 event_count;
 451};
 452
 453static int uio_open(struct inode *inode, struct file *filep)
 454{
 455        struct uio_device *idev;
 456        struct uio_listener *listener;
 457        int ret = 0;
 458
 459        mutex_lock(&minor_lock);
 460        idev = idr_find(&uio_idr, iminor(inode));
 461        mutex_unlock(&minor_lock);
 462        if (!idev) {
 463                ret = -ENODEV;
 464                goto out;
 465        }
 466
 467        if (!try_module_get(idev->owner)) {
 468                ret = -ENODEV;
 469                goto out;
 470        }
 471
 472        listener = kmalloc(sizeof(*listener), GFP_KERNEL);
 473        if (!listener) {
 474                ret = -ENOMEM;
 475                goto err_alloc_listener;
 476        }
 477
 478        listener->dev = idev;
 479        listener->event_count = atomic_read(&idev->event);
 480        filep->private_data = listener;
 481
 482        if (idev->info->open) {
 483                ret = idev->info->open(idev->info, inode);
 484                if (ret)
 485                        goto err_infoopen;
 486        }
 487        return 0;
 488
 489err_infoopen:
 490        kfree(listener);
 491
 492err_alloc_listener:
 493        module_put(idev->owner);
 494
 495out:
 496        return ret;
 497}
 498
 499static int uio_fasync(int fd, struct file *filep, int on)
 500{
 501        struct uio_listener *listener = filep->private_data;
 502        struct uio_device *idev = listener->dev;
 503
 504        return fasync_helper(fd, filep, on, &idev->async_queue);
 505}
 506
 507static int uio_release(struct inode *inode, struct file *filep)
 508{
 509        int ret = 0;
 510        struct uio_listener *listener = filep->private_data;
 511        struct uio_device *idev = listener->dev;
 512
 513        if (idev->info->release)
 514                ret = idev->info->release(idev->info, inode);
 515
 516        module_put(idev->owner);
 517        kfree(listener);
 518        return ret;
 519}
 520
 521static unsigned int uio_poll(struct file *filep, poll_table *wait)
 522{
 523        struct uio_listener *listener = filep->private_data;
 524        struct uio_device *idev = listener->dev;
 525
 526        if (idev->info->irq == UIO_IRQ_NONE)
 527                return -EIO;
 528
 529        poll_wait(filep, &idev->wait, wait);
 530        if (listener->event_count != atomic_read(&idev->event))
 531                return POLLIN | POLLRDNORM;
 532        return 0;
 533}
 534
 535static ssize_t uio_read(struct file *filep, char __user *buf,
 536                        size_t count, loff_t *ppos)
 537{
 538        struct uio_listener *listener = filep->private_data;
 539        struct uio_device *idev = listener->dev;
 540        DECLARE_WAITQUEUE(wait, current);
 541        ssize_t retval;
 542        s32 event_count;
 543
 544        if (idev->info->irq == UIO_IRQ_NONE)
 545                return -EIO;
 546
 547        if (count != sizeof(s32))
 548                return -EINVAL;
 549
 550        add_wait_queue(&idev->wait, &wait);
 551
 552        do {
 553                set_current_state(TASK_INTERRUPTIBLE);
 554
 555                event_count = atomic_read(&idev->event);
 556                if (event_count != listener->event_count) {
 557                        if (copy_to_user(buf, &event_count, count))
 558                                retval = -EFAULT;
 559                        else {
 560                                listener->event_count = event_count;
 561                                retval = count;
 562                        }
 563                        break;
 564                }
 565
 566                if (filep->f_flags & O_NONBLOCK) {
 567                        retval = -EAGAIN;
 568                        break;
 569                }
 570
 571                if (signal_pending(current)) {
 572                        retval = -ERESTARTSYS;
 573                        break;
 574                }
 575                schedule();
 576        } while (1);
 577
 578        __set_current_state(TASK_RUNNING);
 579        remove_wait_queue(&idev->wait, &wait);
 580
 581        return retval;
 582}
 583
 584static ssize_t uio_write(struct file *filep, const char __user *buf,
 585                        size_t count, loff_t *ppos)
 586{
 587        struct uio_listener *listener = filep->private_data;
 588        struct uio_device *idev = listener->dev;
 589        ssize_t retval;
 590        s32 irq_on;
 591
 592        if (idev->info->irq == UIO_IRQ_NONE)
 593                return -EIO;
 594
 595        if (count != sizeof(s32))
 596                return -EINVAL;
 597
 598        if (!idev->info->irqcontrol)
 599                return -ENOSYS;
 600
 601        if (copy_from_user(&irq_on, buf, count))
 602                return -EFAULT;
 603
 604        retval = idev->info->irqcontrol(idev->info, irq_on);
 605
 606        return retval ? retval : sizeof(s32);
 607}
 608
 609static int uio_find_mem_index(struct vm_area_struct *vma)
 610{
 611        int mi;
 612        struct uio_device *idev = vma->vm_private_data;
 613
 614        for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
 615                if (idev->info->mem[mi].size == 0)
 616                        return -1;
 617                if (vma->vm_pgoff == mi)
 618                        return mi;
 619        }
 620        return -1;
 621}
 622
 623static void uio_vma_open(struct vm_area_struct *vma)
 624{
 625        struct uio_device *idev = vma->vm_private_data;
 626        idev->vma_count++;
 627}
 628
 629static void uio_vma_close(struct vm_area_struct *vma)
 630{
 631        struct uio_device *idev = vma->vm_private_data;
 632        idev->vma_count--;
 633}
 634
 635static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 636{
 637        struct uio_device *idev = vma->vm_private_data;
 638        struct page *page;
 639        unsigned long offset;
 640
 641        int mi = uio_find_mem_index(vma);
 642        if (mi < 0)
 643                return VM_FAULT_SIGBUS;
 644
 645        /*
 646         * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
 647         * to use mem[N].
 648         */
 649        offset = (vmf->pgoff - mi) << PAGE_SHIFT;
 650
 651        if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
 652                page = virt_to_page(idev->info->mem[mi].addr + offset);
 653        else
 654                page = vmalloc_to_page((void *)idev->info->mem[mi].addr
 655                                                        + offset);
 656        get_page(page);
 657        vmf->page = page;
 658        return 0;
 659}
 660
 661static struct vm_operations_struct uio_vm_ops = {
 662        .open = uio_vma_open,
 663        .close = uio_vma_close,
 664        .fault = uio_vma_fault,
 665};
 666
 667static int uio_mmap_physical(struct vm_area_struct *vma)
 668{
 669        struct uio_device *idev = vma->vm_private_data;
 670        int mi = uio_find_mem_index(vma);
 671        if (mi < 0)
 672                return -EINVAL;
 673
 674        vma->vm_flags |= VM_IO | VM_RESERVED;
 675
 676        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 677
 678        return remap_pfn_range(vma,
 679                               vma->vm_start,
 680                               idev->info->mem[mi].addr >> PAGE_SHIFT,
 681                               vma->vm_end - vma->vm_start,
 682                               vma->vm_page_prot);
 683}
 684
 685static int uio_mmap_logical(struct vm_area_struct *vma)
 686{
 687        vma->vm_flags |= VM_RESERVED;
 688        vma->vm_ops = &uio_vm_ops;
 689        uio_vma_open(vma);
 690        return 0;
 691}
 692
 693static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
 694{
 695        struct uio_listener *listener = filep->private_data;
 696        struct uio_device *idev = listener->dev;
 697        int mi;
 698        unsigned long requested_pages, actual_pages;
 699        int ret = 0;
 700
 701        if (vma->vm_end < vma->vm_start)
 702                return -EINVAL;
 703
 704        vma->vm_private_data = idev;
 705
 706        mi = uio_find_mem_index(vma);
 707        if (mi < 0)
 708                return -EINVAL;
 709
 710        requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 711        actual_pages = ((idev->info->mem[mi].addr & ~PAGE_MASK)
 712                        + idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
 713        if (requested_pages > actual_pages)
 714                return -EINVAL;
 715
 716        if (idev->info->mmap) {
 717                ret = idev->info->mmap(idev->info, vma);
 718                return ret;
 719        }
 720
 721        switch (idev->info->mem[mi].memtype) {
 722                case UIO_MEM_PHYS:
 723                        return uio_mmap_physical(vma);
 724                case UIO_MEM_LOGICAL:
 725                case UIO_MEM_VIRTUAL:
 726                        return uio_mmap_logical(vma);
 727                default:
 728                        return -EINVAL;
 729        }
 730}
 731
 732static const struct file_operations uio_fops = {
 733        .owner          = THIS_MODULE,
 734        .open           = uio_open,
 735        .release        = uio_release,
 736        .read           = uio_read,
 737        .write          = uio_write,
 738        .mmap           = uio_mmap,
 739        .poll           = uio_poll,
 740        .fasync         = uio_fasync,
 741};
 742
 743static int uio_major_init(void)
 744{
 745        uio_major = register_chrdev(0, "uio", &uio_fops);
 746        if (uio_major < 0)
 747                return uio_major;
 748        return 0;
 749}
 750
 751static void uio_major_cleanup(void)
 752{
 753        unregister_chrdev(uio_major, "uio");
 754}
 755
 756static int init_uio_class(void)
 757{
 758        int ret = 0;
 759
 760        if (uio_class != NULL) {
 761                kref_get(&uio_class->kref);
 762                goto exit;
 763        }
 764
 765        /* This is the first time in here, set everything up properly */
 766        ret = uio_major_init();
 767        if (ret)
 768                goto exit;
 769
 770        uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
 771        if (!uio_class) {
 772                ret = -ENOMEM;
 773                goto err_kzalloc;
 774        }
 775
 776        kref_init(&uio_class->kref);
 777        uio_class->class = class_create(THIS_MODULE, "uio");
 778        if (IS_ERR(uio_class->class)) {
 779                ret = IS_ERR(uio_class->class);
 780                printk(KERN_ERR "class_create failed for uio\n");
 781                goto err_class_create;
 782        }
 783        return 0;
 784
 785err_class_create:
 786        kfree(uio_class);
 787        uio_class = NULL;
 788err_kzalloc:
 789        uio_major_cleanup();
 790exit:
 791        return ret;
 792}
 793
 794static void release_uio_class(struct kref *kref)
 795{
 796        /* Ok, we cheat as we know we only have one uio_class */
 797        class_destroy(uio_class->class);
 798        kfree(uio_class);
 799        uio_major_cleanup();
 800        uio_class = NULL;
 801}
 802
 803static void uio_class_destroy(void)
 804{
 805        if (uio_class)
 806                kref_put(&uio_class->kref, release_uio_class);
 807}
 808
 809/**
 810 * uio_register_device - register a new userspace IO device
 811 * @owner:      module that creates the new device
 812 * @parent:     parent device
 813 * @info:       UIO device capabilities
 814 *
 815 * returns zero on success or a negative error code.
 816 */
 817int __uio_register_device(struct module *owner,
 818                          struct device *parent,
 819                          struct uio_info *info)
 820{
 821        struct uio_device *idev;
 822        int ret = 0;
 823
 824        if (!parent || !info || !info->name || !info->version)
 825                return -EINVAL;
 826
 827        info->uio_dev = NULL;
 828
 829        ret = init_uio_class();
 830        if (ret)
 831                return ret;
 832
 833        idev = kzalloc(sizeof(*idev), GFP_KERNEL);
 834        if (!idev) {
 835                ret = -ENOMEM;
 836                goto err_kzalloc;
 837        }
 838
 839        idev->owner = owner;
 840        idev->info = info;
 841        init_waitqueue_head(&idev->wait);
 842        atomic_set(&idev->event, 0);
 843
 844        ret = uio_get_minor(idev);
 845        if (ret)
 846                goto err_get_minor;
 847
 848        idev->dev = device_create(uio_class->class, parent,
 849                                  MKDEV(uio_major, idev->minor), idev,
 850                                  "uio%d", idev->minor);
 851        if (IS_ERR(idev->dev)) {
 852                printk(KERN_ERR "UIO: device register failed\n");
 853                ret = PTR_ERR(idev->dev);
 854                goto err_device_create;
 855        }
 856
 857        ret = uio_dev_add_attributes(idev);
 858        if (ret)
 859                goto err_uio_dev_add_attributes;
 860
 861        info->uio_dev = idev;
 862
 863        if (idev->info->irq >= 0) {
 864                ret = request_irq(idev->info->irq, uio_interrupt,
 865                                  idev->info->irq_flags, idev->info->name, idev);
 866                if (ret)
 867                        goto err_request_irq;
 868        }
 869
 870        return 0;
 871
 872err_request_irq:
 873        uio_dev_del_attributes(idev);
 874err_uio_dev_add_attributes:
 875        device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
 876err_device_create:
 877        uio_free_minor(idev);
 878err_get_minor:
 879        kfree(idev);
 880err_kzalloc:
 881        uio_class_destroy();
 882        return ret;
 883}
 884EXPORT_SYMBOL_GPL(__uio_register_device);
 885
 886/**
 887 * uio_unregister_device - unregister a industrial IO device
 888 * @info:       UIO device capabilities
 889 *
 890 */
 891void uio_unregister_device(struct uio_info *info)
 892{
 893        struct uio_device *idev;
 894
 895        if (!info || !info->uio_dev)
 896                return;
 897
 898        idev = info->uio_dev;
 899
 900        uio_free_minor(idev);
 901
 902        if (info->irq >= 0)
 903                free_irq(info->irq, idev);
 904
 905        uio_dev_del_attributes(idev);
 906
 907        dev_set_drvdata(idev->dev, NULL);
 908        device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
 909        kfree(idev);
 910        uio_class_destroy();
 911
 912        return;
 913}
 914EXPORT_SYMBOL_GPL(uio_unregister_device);
 915
 916static int __init uio_init(void)
 917{
 918        return 0;
 919}
 920
 921static void __exit uio_exit(void)
 922{
 923}
 924
 925module_init(uio_init)
 926module_exit(uio_exit)
 927MODULE_LICENSE("GPL v2");
 928
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.