Index: module/dvb_loopback.c =================================================================== --- module/dvb_loopback.c (revision 24) +++ module/dvb_loopback.c (working copy) @@ -175,6 +175,7 @@ static int get_new_filemap(struct dvblb_devinfo *lbdev, int id) { int i; for(i = 0; i < DVBLB_MAXFD; i++) + { if(lbdev->filemap[i] == NULL) { if(id) lbdev->filemap[i] = lbdev->user_dev; @@ -182,6 +183,7 @@ lbdev->filemap[i] = lbdev->lb_dev; return i; } + } return -1; } @@ -207,10 +209,10 @@ int ret = 0; dprintk2("dvblb_fake_ioctl (%d) : %lu\n", lbdev->parent->adapter.num, 0xFF & cmd); - if (down_interruptible(&lbdev->lock_fake_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_fake_ioctl)) return -ERESTARTSYS; - if (down_interruptible(&lbdev->lock_ioctl)) { - up(&lbdev->lock_fake_ioctl); + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) { + mutex_unlock(&lbdev->lock_fake_ioctl); return -ERESTARTSYS; } //printk("Sleep up on cmd: %u\n", cmd); @@ -228,7 +230,7 @@ lbdev->ioctldata = arg; //kill_proc(lbdev->pid, SIGIO, 1); - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); wake_up_interruptible(&lbdev->wait_virt_poll); while(1) { ret = wait_event_interruptible_timeout(lbdev->wait_ioctl, @@ -249,20 +251,20 @@ could do something about it here */ printk("dvblb_fake_ioctl interrupted: %lu\n", lbdev->ioctlcmd); - up(&lbdev->lock_fake_ioctl); + mutex_unlock(&lbdev->lock_fake_ioctl); return -1; } dprintk("dvbloopback: timeout waiting for userspace\n"); } - if (down_interruptible(&lbdev->lock_ioctl)) { - up(&lbdev->lock_fake_ioctl); + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) { + mutex_unlock(&lbdev->lock_fake_ioctl); return -ERESTARTSYS; } //printk("Woke up on cmd: %u\n", cmd); if (lbdev->ioctlcmd != ULONG_MAX) { - up(&lbdev->lock_ioctl); - up(&lbdev->lock_fake_ioctl); + mutex_unlock(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_fake_ioctl); printk("dvblb_fake_ioctl failed: %lu\n",lbdev->ioctlcmd); return -1; } @@ -271,8 +273,8 @@ memcpy(arg, lbdev->ioctlretdata + sizeof(int), lbdev->ioctllen); ret = lbdev->ioctlretval; - up(&lbdev->lock_ioctl); - up(&lbdev->lock_fake_ioctl); + mutex_unlock(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_fake_ioctl); return ret; } @@ -300,28 +302,32 @@ struct dvblb_custommsg ci; /*must update private_data so we can map fds properly */ - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; map = get_new_filemap(lbdev, 0); if (map < 0) { printk("dvblb_open %s: Failed to set filemap\n", dnames[dvbdev->type]); + mutex_unlock(&lbdev->lock_ioctl); return -EBUSY; } - lbdev->dbgfilemap[map] = f; + try_module_get(THIS_MODULE); + lbdev->dbgfilemap[map] = f; f->private_data = &lbdev->filemap[map]; lbdev->poll_waiting = 0; - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); dprintk("dvblb_open %s: fd: %d\n", dnames[dvbdev->type], map); if (lbdev->forward_dev) { ret = dvblb_forward_open(lbdev, inode, f); if(ret < 0) { + module_put(THIS_MODULE); lbdev->filemap[map] = NULL; } return ret; } if (lbdev->pid == -1) { + module_put(THIS_MODULE); lbdev->filemap[map] = NULL; return -EFAULT; } @@ -330,8 +336,10 @@ ret = dvblb_fake_ioctl(lbdev, &lbdev->filemap[map], DVBLB_CMD_OPEN, &ci); if(ret < 0) { + module_put(THIS_MODULE); lbdev->filemap[map] = NULL; } + return ret; } /* This is the userspace control device */ @@ -342,13 +350,20 @@ lbdev->pid = current->pid; lbdev->ioctlcmd = ULONG_MAX; lbdev->ioctllen = 0; - down(&lbdev->lock_ioctl); + mutex_lock(&lbdev->lock_ioctl); memset(lbdev->filemap, 0, sizeof(lbdev->filemap)); map = get_new_filemap(lbdev, 1); + if (map < 0) { + printk("dvblb_open %s: Failed to set filemap\n", + dnames[dvbdev->type]); + mutex_unlock(&lbdev->lock_ioctl); + return -EBUSY; + } + try_module_get(THIS_MODULE); f->private_data = &lbdev->filemap[map]; lbdev->dbgfilemap[map] = f; lbdev->poll_waiting = 0; - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); dprintk("dvblb_open %s: fd: %d\n", dnames[dvbdev->type], map); } return ret; @@ -358,7 +373,7 @@ { struct dvb_device *dvbdev, **filemap; struct dvblb_devinfo *lbdev; - int err; + int ret; filemap = (struct dvb_device **) f->private_data; if(filemap == NULL) { @@ -378,42 +393,52 @@ dprintk("dvblb_release %d%s%d fd:%d\n", lbdev->parent->adapter.num, dnames[dvbdev->type], dvbdev->id, find_filemap(lbdev, filemap)); + if(dvbdev->id == 0) { /* This is the looped device */ struct dvblb_custommsg ci; - int ret; if (lbdev->forward_dev) { ret = dvblb_forward_release(lbdev, f); *filemap = NULL; - return ret; + goto out; } - if (lbdev->pid == -1) - return -EFAULT; + if (lbdev->pid == -1) { + ret = -EFAULT; + goto out; + } ci.type = DVBLB_CLOSE; ret = dvblb_fake_ioctl(lbdev, filemap, DVBLB_CMD_CLOSE, &ci); - if (down_interruptible(&lbdev->lock_ioctl)) - return -ERESTARTSYS; + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) { + ret = -ERESTARTSYS; + goto out; + } lbdev->poll_waiting = 0; *filemap = NULL; - up(&lbdev->lock_ioctl); - return ret; + mutex_unlock(&lbdev->lock_ioctl); + goto out; } /* This is the userspace control device */ *filemap = NULL; f->private_data = dvbdev; - err = dvb_generic_release(inode, f); - if (err < 0) - return err; + ret = dvb_generic_release(inode, f); + if (ret < 0) { + goto out; + } lbdev->pid = -1; - down_interruptible(&lbdev->lock_buffer); + mutex_lock_interruptible(&lbdev->lock_buffer); if (lbdev->buffer) { rvfree(lbdev->buffer, lbdev->buflen*N_BUFFS); lbdev->buffer = NULL; } - up(&lbdev->lock_buffer); - return 0; + mutex_unlock(&lbdev->lock_buffer); + ret = 0; + goto out; + +out: + module_put(THIS_MODULE); + return ret; } static ssize_t dvblb_write(struct file *f, const char *buf, @@ -482,20 +507,20 @@ ci.u.count = count; if (lbdev->pid == -1) return -EFAULT; - if (down_interruptible(&lbdev->lock_buffer)) + if (mutex_lock_interruptible(&lbdev->lock_buffer)) return -ERESTARTSYS; if(dvblb_fake_ioctl(lbdev, filemap, DVBLB_CMD_READ, &ci) < 0 || ! lbdev->buffer) { - up(&lbdev->lock_buffer); + mutex_unlock(&lbdev->lock_buffer); return 0; } if (ci.u.count > lbdev->buflen) ci.u.count = lbdev->buflen; if (copy_to_user(buf, lbdev->buffer, ci.u.count)) { - up(&lbdev->lock_buffer); + mutex_unlock(&lbdev->lock_buffer); return -EFAULT; } - up(&lbdev->lock_buffer); + mutex_unlock(&lbdev->lock_buffer); dprintk3("Read %ld bytes\n", (long)ci.u.count); return ci.u.count; } else { @@ -503,7 +528,7 @@ /* We pass ioctls to the userspace driver this way */ unsigned long int cmd, base_size, size; base_size = sizeof(cmd) + sizeof(lbdev->ioctlfd); - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; cmd = lbdev->ioctlcmd; @@ -511,7 +536,7 @@ sizeof(int); if (count < base_size + size || lbdev->ioctlcmd == ULONG_MAX || lbdev->ioctl_already_read) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return -EFAULT; } if (cmd == ULONG_MAX) @@ -520,32 +545,32 @@ count = size + base_size; if (copy_to_user(buf, &cmd, sizeof(cmd))) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return -EFAULT; } if (copy_to_user(buf + sizeof(cmd), &lbdev->ioctlfd, sizeof(lbdev->ioctlfd))) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return -EFAULT; } if (lbdev->ioctllen == 0) { if (copy_to_user(buf + base_size, &lbdev->ioctldata, size)) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return -EFAULT; } } else { if (copy_to_user(buf + base_size, lbdev->ioctldata, size)) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return -EFAULT; } } lbdev->ioctl_already_read = 1; - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return count; } } @@ -627,7 +652,7 @@ printk("Failed to read pollmsg from ioctl\n"); return -EFAULT; } - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; if (pollmsg.count == 0) { /* Send wakeup to all waiting polls */ @@ -651,16 +676,16 @@ wake_up_interruptible(&lbdev->wait_poll[pos]); } } - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return 0; } - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; if (cmd != lbdev->ioctlcmd) { // Incorrect response printk("dvbloopback: Got wrong response (%u != %lu)\n", cmd, lbdev->ioctlcmd); - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return 0; } if (cmd < DVBLB_MAX_CMDS) @@ -671,12 +696,12 @@ size = sizeof(int) + _IOC_SIZE(cmd); if (copy_from_user(lbdev->ioctlretdata, parg, size)) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return -EFAULT; } lbdev->ioctlretval = *(int *)lbdev->ioctlretdata; lbdev->ioctlcmd = ULONG_MAX; - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); wake_up(&lbdev->wait_ioctl); return 0; } @@ -717,7 +742,7 @@ /* This is the userspace control device */ if (!size) return -EINVAL; - if (down_interruptible(&lbdev->lock_buffer)) + if (mutex_lock_interruptible(&lbdev->lock_buffer)) return -ERESTARTSYS; if (lbdev->buffer) rvfree(lbdev->buffer, lbdev->buflen*N_BUFFS); @@ -725,28 +750,28 @@ lbdev->buffer=rvmalloc(lbdev->buflen*N_BUFFS); if (lbdev->buffer == NULL) { - up(&lbdev->lock_buffer); + mutex_unlock(&lbdev->lock_buffer); return -EINVAL; } if (size > (((N_BUFFS * lbdev->buflen) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { - up(&lbdev->lock_buffer); + mutex_unlock(&lbdev->lock_buffer); return -EINVAL; } - pos = (unsigned long)lbdev->buffer; + pos = (unsigned long)lbdev->buffer; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, - PAGE_SHARED)) { - up(&lbdev->lock_buffer); + PAGE_SHARED)) { + mutex_unlock(&lbdev->lock_buffer); return -EAGAIN; } start += PAGE_SIZE; - pos += PAGE_SIZE; + pos += PAGE_SIZE; size -= PAGE_SIZE; } - up(&lbdev->lock_buffer); + mutex_unlock(&lbdev->lock_buffer); return 0; } @@ -796,13 +821,13 @@ } poll_wait(f, &lbdev->wait_poll[pos], wait); - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; if(lbdev->poll_waiting & (1 << pos)) do_poll = 0; else /* need to set it before the fake_ioctl to prevent race */ lbdev->poll_waiting |= (1 << pos); - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); if(do_poll) { ci.type = DVBLB_POLL; @@ -810,10 +835,10 @@ ret = dvblb_fake_ioctl(lbdev, filemap, DVBLB_CMD_POLL, &ci); if(ret != 0) { - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; lbdev->poll_waiting &= ~(1 << pos); - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); if(ret < 0) return ret; } @@ -832,13 +857,13 @@ } poll_wait(f, &lbdev->wait_virt_poll, wait); - if (down_interruptible(&lbdev->lock_ioctl)) + if (mutex_lock_interruptible(&lbdev->lock_ioctl)) return -ERESTARTSYS; if (lbdev->ioctlcmd != ULONG_MAX && ! lbdev->ioctl_already_read) { - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return (POLLIN | POLLPRI | POLLRDNORM); } - up(&lbdev->lock_ioctl); + mutex_unlock(&lbdev->lock_ioctl); return 0; } @@ -934,9 +959,9 @@ } init_waitqueue_head(&lbdev->wait_virt_poll); init_waitqueue_head(&lbdev->wait_ioctl); - init_MUTEX(&lbdev->lock_fake_ioctl); - init_MUTEX(&lbdev->lock_ioctl); - init_MUTEX(&lbdev->lock_buffer); + mutex_init(&lbdev->lock_fake_ioctl); + mutex_init(&lbdev->lock_ioctl); + mutex_init(&lbdev->lock_buffer); dvblb->init |= (1 << dev_idx); return 0; } @@ -1000,7 +1025,7 @@ } printk("dvbloopback: registering %d adapters\n", num_adapters); - dvblb_global = vmalloc(sizeof(struct dvblb) * num_adapters); + dvblb_global = kmalloc(sizeof(struct dvblb) * num_adapters, GFP_KERNEL); if (dvblb_global == NULL) return -ENOMEM; for(i=0; i < num_adapters; i++) @@ -1008,13 +1033,13 @@ dvblb_basedev = platform_device_alloc("dvbloopback", -1); if (!dvblb_basedev) { - vfree(dvblb_global); + kfree(dvblb_global); return -ENOMEM; } ret = platform_device_add(dvblb_basedev); if (ret) { platform_device_put(dvblb_basedev); - vfree(dvblb_global); + kfree(dvblb_global); return ret; } for(i=0; i < num_adapters; i++) { @@ -1096,7 +1121,7 @@ destroy_lb_adapter(&dvblb_global[i]); } platform_device_unregister(dvblb_basedev); - vfree(dvblb_global); + kfree(dvblb_global); return -EFAULT; } return 0; @@ -1112,7 +1137,7 @@ destroy_lb_adapter(&dvblb_global[i]); } platform_device_unregister(dvblb_basedev); - vfree(dvblb_global); + kfree(dvblb_global); dvblb_uninit_procfs(); } Index: module/dvblb_internal.h =================================================================== --- module/dvblb_internal.h (revision 24) +++ module/dvblb_internal.h (working copy) @@ -28,9 +28,9 @@ unsigned long int buflen; wait_queue_head_t wait_ioctl; wait_queue_head_t wait_virt_poll; - struct semaphore lock_fake_ioctl; - struct semaphore lock_ioctl; - struct semaphore lock_buffer; + struct mutex lock_fake_ioctl; + struct mutex lock_ioctl; + struct mutex lock_buffer; wait_queue_head_t wait_poll[DVBLB_MAXFD]; unsigned long int poll_waiting;