Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: most: destroy cdev when channel gets disconnected

When a channel is being removed while an application holds the
corresponding character device, this device is going to be destroyed only
after the application closes the file descriptor and releases character
device. In case the channel appears again before the application closes the
file descriptor it holds, the channel cannot be linked.

This patch changes the described behavior and destroys the character
device at the time the channel get disconnected from the AIM.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Andrey Shvetsov and committed by
Greg Kroah-Hartman
2c4aaa1f 5f788625

+10 -6
+10 -6
drivers/staging/most/aim-cdev/cdev.c
··· 99 99 100 100 device_destroy(aim_class, c->devno); 101 101 cdev_del(&c->cdev); 102 - kfifo_free(&c->fifo); 103 102 spin_lock_irqsave(&ch_list_lock, flags); 104 103 list_del(&c->list); 105 104 spin_unlock_irqrestore(&ch_list_lock, flags); 105 + } 106 + 107 + static void destroy_channel(struct aim_channel *c) 108 + { 106 109 ida_simple_remove(&minor_id, MINOR(c->devno)); 110 + kfifo_free(&c->fifo); 111 + kfree(c); 107 112 } 108 113 109 114 /** ··· 175 170 stop_channel(c); 176 171 mutex_unlock(&c->io_mutex); 177 172 } else { 178 - destroy_cdev(c); 179 173 mutex_unlock(&c->io_mutex); 180 - kfree(c); 174 + destroy_channel(c); 181 175 } 182 176 return 0; 183 177 } ··· 341 337 spin_lock(&c->unlink); 342 338 c->dev = NULL; 343 339 spin_unlock(&c->unlink); 340 + destroy_cdev(c); 344 341 if (c->access_ref) { 345 342 stop_channel(c); 346 343 wake_up_interruptible(&c->wq); 347 344 mutex_unlock(&c->io_mutex); 348 345 } else { 349 - destroy_cdev(c); 350 346 mutex_unlock(&c->io_mutex); 351 - kfree(c); 347 + destroy_channel(c); 352 348 } 353 349 return 0; 354 350 } ··· 550 546 551 547 list_for_each_entry_safe(c, tmp, &channel_list, list) { 552 548 destroy_cdev(c); 553 - kfree(c); 549 + destroy_channel(c); 554 550 } 555 551 class_destroy(aim_class); 556 552 unregister_chrdev_region(aim_devno, 1);