Commit 2c4aaa1f authored by Andrey Shvetsov's avatar Andrey Shvetsov Committed by Greg Kroah-Hartman

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: default avatarAndrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: default avatarChristian Gromm <christian.gromm@microchip.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5f788625
...@@ -99,11 +99,16 @@ static void destroy_cdev(struct aim_channel *c) ...@@ -99,11 +99,16 @@ static void destroy_cdev(struct aim_channel *c)
device_destroy(aim_class, c->devno); device_destroy(aim_class, c->devno);
cdev_del(&c->cdev); cdev_del(&c->cdev);
kfifo_free(&c->fifo);
spin_lock_irqsave(&ch_list_lock, flags); spin_lock_irqsave(&ch_list_lock, flags);
list_del(&c->list); list_del(&c->list);
spin_unlock_irqrestore(&ch_list_lock, flags); spin_unlock_irqrestore(&ch_list_lock, flags);
}
static void destroy_channel(struct aim_channel *c)
{
ida_simple_remove(&minor_id, MINOR(c->devno)); ida_simple_remove(&minor_id, MINOR(c->devno));
kfifo_free(&c->fifo);
kfree(c);
} }
/** /**
...@@ -170,9 +175,8 @@ static int aim_close(struct inode *inode, struct file *filp) ...@@ -170,9 +175,8 @@ static int aim_close(struct inode *inode, struct file *filp)
stop_channel(c); stop_channel(c);
mutex_unlock(&c->io_mutex); mutex_unlock(&c->io_mutex);
} else { } else {
destroy_cdev(c);
mutex_unlock(&c->io_mutex); mutex_unlock(&c->io_mutex);
kfree(c); destroy_channel(c);
} }
return 0; return 0;
} }
...@@ -337,14 +341,14 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) ...@@ -337,14 +341,14 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
spin_lock(&c->unlink); spin_lock(&c->unlink);
c->dev = NULL; c->dev = NULL;
spin_unlock(&c->unlink); spin_unlock(&c->unlink);
destroy_cdev(c);
if (c->access_ref) { if (c->access_ref) {
stop_channel(c); stop_channel(c);
wake_up_interruptible(&c->wq); wake_up_interruptible(&c->wq);
mutex_unlock(&c->io_mutex); mutex_unlock(&c->io_mutex);
} else { } else {
destroy_cdev(c);
mutex_unlock(&c->io_mutex); mutex_unlock(&c->io_mutex);
kfree(c); destroy_channel(c);
} }
return 0; return 0;
} }
...@@ -546,7 +550,7 @@ static void __exit mod_exit(void) ...@@ -546,7 +550,7 @@ static void __exit mod_exit(void)
list_for_each_entry_safe(c, tmp, &channel_list, list) { list_for_each_entry_safe(c, tmp, &channel_list, list) {
destroy_cdev(c); destroy_cdev(c);
kfree(c); destroy_channel(c);
} }
class_destroy(aim_class); class_destroy(aim_class);
unregister_chrdev_region(aim_devno, 1); unregister_chrdev_region(aim_devno, 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment