Loading drivers/gpio/gpiolib-cdev.c +47 −158 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/poll.h> #include <linux/rbtree.h> #include <linux/rwsem.h> #include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/timekeeping.h> Loading Loading @@ -65,45 +66,6 @@ typedef long (*ioctl_fn)(struct file *, unsigned int, unsigned long); typedef ssize_t (*read_fn)(struct file *, char __user *, size_t count, loff_t *); static __poll_t call_poll_locked(struct file *file, struct poll_table_struct *wait, struct gpio_device *gdev, poll_fn func) { __poll_t ret; down_read(&gdev->sem); ret = func(file, wait); up_read(&gdev->sem); return ret; } static long call_ioctl_locked(struct file *file, unsigned int cmd, unsigned long arg, struct gpio_device *gdev, ioctl_fn func) { long ret; down_read(&gdev->sem); ret = func(file, cmd, arg); up_read(&gdev->sem); return ret; } static ssize_t call_read_locked(struct file *file, char __user *buf, size_t count, loff_t *f_ps, struct gpio_device *gdev, read_fn func) { ssize_t ret; down_read(&gdev->sem); ret = func(file, buf, count, f_ps); up_read(&gdev->sem); return ret; } /* * GPIO line handle management */ Loading Loading @@ -238,7 +200,7 @@ static long linehandle_set_config(struct linehandle_state *lh, return 0; } static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, static long linehandle_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linehandle_state *lh = file->private_data; Loading @@ -248,6 +210,8 @@ static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned int i; int ret; guard(rwsem_read)(&lh->gdev->sem); if (!lh->gdev->chip) return -ENODEV; Loading Loading @@ -297,15 +261,6 @@ static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, } } static long linehandle_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linehandle_state *lh = file->private_data; return call_ioctl_locked(file, cmd, arg, lh->gdev, linehandle_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long linehandle_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -1564,12 +1519,14 @@ static long linereq_set_config(struct linereq *lr, void __user *ip) return 0; } static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, static long linereq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linereq *lr = file->private_data; void __user *ip = (void __user *)arg; guard(rwsem_read)(&lr->gdev->sem); if (!lr->gdev->chip) return -ENODEV; Loading @@ -1585,15 +1542,6 @@ static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, } } static long linereq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linereq *lr = file->private_data; return call_ioctl_locked(file, cmd, arg, lr->gdev, linereq_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long linereq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading @@ -1602,12 +1550,14 @@ static long linereq_ioctl_compat(struct file *file, unsigned int cmd, } #endif static __poll_t linereq_poll_unlocked(struct file *file, static __poll_t linereq_poll(struct file *file, struct poll_table_struct *wait) { struct linereq *lr = file->private_data; __poll_t events = 0; guard(rwsem_read)(&lr->gdev->sem); if (!lr->gdev->chip) return EPOLLHUP | EPOLLERR; Loading @@ -1620,15 +1570,7 @@ static __poll_t linereq_poll_unlocked(struct file *file, return events; } static __poll_t linereq_poll(struct file *file, struct poll_table_struct *wait) { struct linereq *lr = file->private_data; return call_poll_locked(file, wait, lr->gdev, linereq_poll_unlocked); } static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, static ssize_t linereq_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct linereq *lr = file->private_data; Loading @@ -1636,6 +1578,8 @@ static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, ssize_t bytes_read = 0; int ret; guard(rwsem_read)(&lr->gdev->sem); if (!lr->gdev->chip) return -ENODEV; Loading Loading @@ -1677,15 +1621,6 @@ static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, return bytes_read; } static ssize_t linereq_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct linereq *lr = file->private_data; return call_read_locked(file, buf, count, f_ps, lr->gdev, linereq_read_unlocked); } static void linereq_free(struct linereq *lr) { struct line *line; Loading Loading @@ -1938,12 +1873,14 @@ struct lineevent_state { (GPIOEVENT_REQUEST_RISING_EDGE | \ GPIOEVENT_REQUEST_FALLING_EDGE) static __poll_t lineevent_poll_unlocked(struct file *file, static __poll_t lineevent_poll(struct file *file, struct poll_table_struct *wait) { struct lineevent_state *le = file->private_data; __poll_t events = 0; guard(rwsem_read)(&le->gdev->sem); if (!le->gdev->chip) return EPOLLHUP | EPOLLERR; Loading @@ -1955,14 +1892,6 @@ static __poll_t lineevent_poll_unlocked(struct file *file, return events; } static __poll_t lineevent_poll(struct file *file, struct poll_table_struct *wait) { struct lineevent_state *le = file->private_data; return call_poll_locked(file, wait, le->gdev, lineevent_poll_unlocked); } static int lineevent_unregistered_notify(struct notifier_block *nb, unsigned long action, void *data) { Loading @@ -1979,7 +1908,7 @@ struct compat_gpioeevent_data { u32 id; }; static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, static ssize_t lineevent_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct lineevent_state *le = file->private_data; Loading @@ -1988,6 +1917,8 @@ static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, ssize_t ge_size; int ret; guard(rwsem_read)(&le->gdev->sem); if (!le->gdev->chip) return -ENODEV; Loading Loading @@ -2042,15 +1973,6 @@ static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, return bytes_read; } static ssize_t lineevent_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct lineevent_state *le = file->private_data; return call_read_locked(file, buf, count, f_ps, le->gdev, lineevent_read_unlocked); } static void lineevent_free(struct lineevent_state *le) { if (le->device_unregistered_nb.notifier_call) Loading @@ -2071,13 +1993,15 @@ static int lineevent_release(struct inode *inode, struct file *file) return 0; } static long lineevent_ioctl_unlocked(struct file *file, unsigned int cmd, static long lineevent_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct lineevent_state *le = file->private_data; void __user *ip = (void __user *)arg; struct gpiohandle_data ghd; guard(rwsem_read)(&le->gdev->sem); if (!le->gdev->chip) return -ENODEV; Loading @@ -2103,15 +2027,6 @@ static long lineevent_ioctl_unlocked(struct file *file, unsigned int cmd, return -EINVAL; } static long lineevent_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct lineevent_state *le = file->private_data; return call_ioctl_locked(file, cmd, arg, le->gdev, lineevent_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long lineevent_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -2584,12 +2499,17 @@ static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip) return 0; } static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct gpio_chardev_data *cdev = file->private_data; struct gpio_device *gdev = cdev->gdev; void __user *ip = (void __user *)arg; guard(rwsem_read)(&gdev->sem); /* We fail any subsequent ioctl():s when the chip is gone */ if (!gdev->chip) return -ENODEV; Loading Loading @@ -2621,17 +2541,6 @@ static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned lo } } /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct gpio_chardev_data *cdev = file->private_data; return call_ioctl_locked(file, cmd, arg, cdev->gdev, gpio_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long gpio_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -2679,12 +2588,14 @@ static int gpio_device_unregistered_notify(struct notifier_block *nb, return NOTIFY_OK; } static __poll_t lineinfo_watch_poll_unlocked(struct file *file, static __poll_t lineinfo_watch_poll(struct file *file, struct poll_table_struct *pollt) { struct gpio_chardev_data *cdev = file->private_data; __poll_t events = 0; guard(rwsem_read)(&cdev->gdev->sem); if (!cdev->gdev->chip) return EPOLLHUP | EPOLLERR; Loading @@ -2697,16 +2608,7 @@ static __poll_t lineinfo_watch_poll_unlocked(struct file *file, return events; } static __poll_t lineinfo_watch_poll(struct file *file, struct poll_table_struct *pollt) { struct gpio_chardev_data *cdev = file->private_data; return call_poll_locked(file, pollt, cdev->gdev, lineinfo_watch_poll_unlocked); } static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, size_t count, loff_t *off) { struct gpio_chardev_data *cdev = file->private_data; Loading @@ -2715,6 +2617,8 @@ static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, int ret; size_t event_size; guard(rwsem_read)(&cdev->gdev->sem); if (!cdev->gdev->chip) return -ENODEV; Loading Loading @@ -2777,15 +2681,6 @@ static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, return bytes_read; } static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, size_t count, loff_t *off) { struct gpio_chardev_data *cdev = file->private_data; return call_read_locked(file, buf, count, off, cdev->gdev, lineinfo_watch_read_unlocked); } /** * gpio_chrdev_open() - open the chardev for ioctl operations * @inode: inode for this chardev Loading @@ -2799,17 +2694,15 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) struct gpio_chardev_data *cdev; int ret = -ENOMEM; down_read(&gdev->sem); guard(rwsem_read)(&gdev->sem); /* Fail on open if the backing gpiochip is gone */ if (!gdev->chip) { ret = -ENODEV; goto out_unlock; } if (!gdev->chip) return -ENODEV; cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) goto out_unlock; return -ENODEV; cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); if (!cdev->watched_lines) Loading Loading @@ -2838,8 +2731,6 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) if (ret) goto out_unregister_device_notifier; up_read(&gdev->sem); return ret; out_unregister_device_notifier: Loading @@ -2853,8 +2744,6 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) bitmap_free(cdev->watched_lines); out_free_cdev: kfree(cdev); out_unlock: up_read(&gdev->sem); return ret; } Loading Loading
drivers/gpio/gpiolib-cdev.c +47 −158 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/poll.h> #include <linux/rbtree.h> #include <linux/rwsem.h> #include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/timekeeping.h> Loading Loading @@ -65,45 +66,6 @@ typedef long (*ioctl_fn)(struct file *, unsigned int, unsigned long); typedef ssize_t (*read_fn)(struct file *, char __user *, size_t count, loff_t *); static __poll_t call_poll_locked(struct file *file, struct poll_table_struct *wait, struct gpio_device *gdev, poll_fn func) { __poll_t ret; down_read(&gdev->sem); ret = func(file, wait); up_read(&gdev->sem); return ret; } static long call_ioctl_locked(struct file *file, unsigned int cmd, unsigned long arg, struct gpio_device *gdev, ioctl_fn func) { long ret; down_read(&gdev->sem); ret = func(file, cmd, arg); up_read(&gdev->sem); return ret; } static ssize_t call_read_locked(struct file *file, char __user *buf, size_t count, loff_t *f_ps, struct gpio_device *gdev, read_fn func) { ssize_t ret; down_read(&gdev->sem); ret = func(file, buf, count, f_ps); up_read(&gdev->sem); return ret; } /* * GPIO line handle management */ Loading Loading @@ -238,7 +200,7 @@ static long linehandle_set_config(struct linehandle_state *lh, return 0; } static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, static long linehandle_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linehandle_state *lh = file->private_data; Loading @@ -248,6 +210,8 @@ static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned int i; int ret; guard(rwsem_read)(&lh->gdev->sem); if (!lh->gdev->chip) return -ENODEV; Loading Loading @@ -297,15 +261,6 @@ static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, } } static long linehandle_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linehandle_state *lh = file->private_data; return call_ioctl_locked(file, cmd, arg, lh->gdev, linehandle_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long linehandle_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -1564,12 +1519,14 @@ static long linereq_set_config(struct linereq *lr, void __user *ip) return 0; } static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, static long linereq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linereq *lr = file->private_data; void __user *ip = (void __user *)arg; guard(rwsem_read)(&lr->gdev->sem); if (!lr->gdev->chip) return -ENODEV; Loading @@ -1585,15 +1542,6 @@ static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, } } static long linereq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct linereq *lr = file->private_data; return call_ioctl_locked(file, cmd, arg, lr->gdev, linereq_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long linereq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading @@ -1602,12 +1550,14 @@ static long linereq_ioctl_compat(struct file *file, unsigned int cmd, } #endif static __poll_t linereq_poll_unlocked(struct file *file, static __poll_t linereq_poll(struct file *file, struct poll_table_struct *wait) { struct linereq *lr = file->private_data; __poll_t events = 0; guard(rwsem_read)(&lr->gdev->sem); if (!lr->gdev->chip) return EPOLLHUP | EPOLLERR; Loading @@ -1620,15 +1570,7 @@ static __poll_t linereq_poll_unlocked(struct file *file, return events; } static __poll_t linereq_poll(struct file *file, struct poll_table_struct *wait) { struct linereq *lr = file->private_data; return call_poll_locked(file, wait, lr->gdev, linereq_poll_unlocked); } static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, static ssize_t linereq_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct linereq *lr = file->private_data; Loading @@ -1636,6 +1578,8 @@ static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, ssize_t bytes_read = 0; int ret; guard(rwsem_read)(&lr->gdev->sem); if (!lr->gdev->chip) return -ENODEV; Loading Loading @@ -1677,15 +1621,6 @@ static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, return bytes_read; } static ssize_t linereq_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct linereq *lr = file->private_data; return call_read_locked(file, buf, count, f_ps, lr->gdev, linereq_read_unlocked); } static void linereq_free(struct linereq *lr) { struct line *line; Loading Loading @@ -1938,12 +1873,14 @@ struct lineevent_state { (GPIOEVENT_REQUEST_RISING_EDGE | \ GPIOEVENT_REQUEST_FALLING_EDGE) static __poll_t lineevent_poll_unlocked(struct file *file, static __poll_t lineevent_poll(struct file *file, struct poll_table_struct *wait) { struct lineevent_state *le = file->private_data; __poll_t events = 0; guard(rwsem_read)(&le->gdev->sem); if (!le->gdev->chip) return EPOLLHUP | EPOLLERR; Loading @@ -1955,14 +1892,6 @@ static __poll_t lineevent_poll_unlocked(struct file *file, return events; } static __poll_t lineevent_poll(struct file *file, struct poll_table_struct *wait) { struct lineevent_state *le = file->private_data; return call_poll_locked(file, wait, le->gdev, lineevent_poll_unlocked); } static int lineevent_unregistered_notify(struct notifier_block *nb, unsigned long action, void *data) { Loading @@ -1979,7 +1908,7 @@ struct compat_gpioeevent_data { u32 id; }; static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, static ssize_t lineevent_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct lineevent_state *le = file->private_data; Loading @@ -1988,6 +1917,8 @@ static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, ssize_t ge_size; int ret; guard(rwsem_read)(&le->gdev->sem); if (!le->gdev->chip) return -ENODEV; Loading Loading @@ -2042,15 +1973,6 @@ static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, return bytes_read; } static ssize_t lineevent_read(struct file *file, char __user *buf, size_t count, loff_t *f_ps) { struct lineevent_state *le = file->private_data; return call_read_locked(file, buf, count, f_ps, le->gdev, lineevent_read_unlocked); } static void lineevent_free(struct lineevent_state *le) { if (le->device_unregistered_nb.notifier_call) Loading @@ -2071,13 +1993,15 @@ static int lineevent_release(struct inode *inode, struct file *file) return 0; } static long lineevent_ioctl_unlocked(struct file *file, unsigned int cmd, static long lineevent_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct lineevent_state *le = file->private_data; void __user *ip = (void __user *)arg; struct gpiohandle_data ghd; guard(rwsem_read)(&le->gdev->sem); if (!le->gdev->chip) return -ENODEV; Loading @@ -2103,15 +2027,6 @@ static long lineevent_ioctl_unlocked(struct file *file, unsigned int cmd, return -EINVAL; } static long lineevent_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct lineevent_state *le = file->private_data; return call_ioctl_locked(file, cmd, arg, le->gdev, lineevent_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long lineevent_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -2584,12 +2499,17 @@ static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip) return 0; } static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct gpio_chardev_data *cdev = file->private_data; struct gpio_device *gdev = cdev->gdev; void __user *ip = (void __user *)arg; guard(rwsem_read)(&gdev->sem); /* We fail any subsequent ioctl():s when the chip is gone */ if (!gdev->chip) return -ENODEV; Loading Loading @@ -2621,17 +2541,6 @@ static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned lo } } /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct gpio_chardev_data *cdev = file->private_data; return call_ioctl_locked(file, cmd, arg, cdev->gdev, gpio_ioctl_unlocked); } #ifdef CONFIG_COMPAT static long gpio_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) Loading Loading @@ -2679,12 +2588,14 @@ static int gpio_device_unregistered_notify(struct notifier_block *nb, return NOTIFY_OK; } static __poll_t lineinfo_watch_poll_unlocked(struct file *file, static __poll_t lineinfo_watch_poll(struct file *file, struct poll_table_struct *pollt) { struct gpio_chardev_data *cdev = file->private_data; __poll_t events = 0; guard(rwsem_read)(&cdev->gdev->sem); if (!cdev->gdev->chip) return EPOLLHUP | EPOLLERR; Loading @@ -2697,16 +2608,7 @@ static __poll_t lineinfo_watch_poll_unlocked(struct file *file, return events; } static __poll_t lineinfo_watch_poll(struct file *file, struct poll_table_struct *pollt) { struct gpio_chardev_data *cdev = file->private_data; return call_poll_locked(file, pollt, cdev->gdev, lineinfo_watch_poll_unlocked); } static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, size_t count, loff_t *off) { struct gpio_chardev_data *cdev = file->private_data; Loading @@ -2715,6 +2617,8 @@ static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, int ret; size_t event_size; guard(rwsem_read)(&cdev->gdev->sem); if (!cdev->gdev->chip) return -ENODEV; Loading Loading @@ -2777,15 +2681,6 @@ static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, return bytes_read; } static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, size_t count, loff_t *off) { struct gpio_chardev_data *cdev = file->private_data; return call_read_locked(file, buf, count, off, cdev->gdev, lineinfo_watch_read_unlocked); } /** * gpio_chrdev_open() - open the chardev for ioctl operations * @inode: inode for this chardev Loading @@ -2799,17 +2694,15 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) struct gpio_chardev_data *cdev; int ret = -ENOMEM; down_read(&gdev->sem); guard(rwsem_read)(&gdev->sem); /* Fail on open if the backing gpiochip is gone */ if (!gdev->chip) { ret = -ENODEV; goto out_unlock; } if (!gdev->chip) return -ENODEV; cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) goto out_unlock; return -ENODEV; cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); if (!cdev->watched_lines) Loading Loading @@ -2838,8 +2731,6 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) if (ret) goto out_unregister_device_notifier; up_read(&gdev->sem); return ret; out_unregister_device_notifier: Loading @@ -2853,8 +2744,6 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) bitmap_free(cdev->watched_lines); out_free_cdev: kfree(cdev); out_unlock: up_read(&gdev->sem); return ret; } Loading