gpiolib-cdev.c (a54756cb24eafac70ce92bfbd9bb4a4195689fb4) gpiolib-cdev.c (7b8e00d981680ddbbdd9874a7b46e0da58a2da4b)
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/anon_inodes.h>
4#include <linux/atomic.h>
5#include <linux/bitmap.h>
6#include <linux/build_bug.h>
7#include <linux/cdev.h>
8#include <linux/compat.h>

--- 802 unchanged lines hidden (view full) ---

811 }
812
813 if (copy_to_user(ip, &lv, sizeof(lv)))
814 return -EFAULT;
815
816 return 0;
817}
818
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/anon_inodes.h>
4#include <linux/atomic.h>
5#include <linux/bitmap.h>
6#include <linux/build_bug.h>
7#include <linux/cdev.h>
8#include <linux/compat.h>

--- 802 unchanged lines hidden (view full) ---

811 }
812
813 if (copy_to_user(ip, &lv, sizeof(lv)))
814 return -EFAULT;
815
816 return 0;
817}
818
819static long linereq_set_values_unlocked(struct linereq *lr,
820 struct gpio_v2_line_values *lv)
821{
822 DECLARE_BITMAP(vals, GPIO_V2_LINES_MAX);
823 struct gpio_desc **descs;
824 unsigned int i, didx, num_set;
825 int ret;
826
827 bitmap_zero(vals, GPIO_V2_LINES_MAX);
828 for (num_set = 0, i = 0; i < lr->num_lines; i++) {
829 if (lv->mask & BIT_ULL(i)) {
830 if (!test_bit(FLAG_IS_OUT, &lr->lines[i].desc->flags))
831 return -EPERM;
832 if (lv->bits & BIT_ULL(i))
833 __set_bit(num_set, vals);
834 num_set++;
835 descs = &lr->lines[i].desc;
836 }
837 }
838 if (num_set == 0)
839 return -EINVAL;
840
841 if (num_set != 1) {
842 /* build compacted desc array and values */
843 descs = kmalloc_array(num_set, sizeof(*descs), GFP_KERNEL);
844 if (!descs)
845 return -ENOMEM;
846 for (didx = 0, i = 0; i < lr->num_lines; i++) {
847 if (lv->mask & BIT_ULL(i)) {
848 descs[didx] = lr->lines[i].desc;
849 didx++;
850 }
851 }
852 }
853 ret = gpiod_set_array_value_complex(false, true, num_set,
854 descs, NULL, vals);
855
856 if (num_set != 1)
857 kfree(descs);
858 return ret;
859}
860
861static long linereq_set_values(struct linereq *lr, void __user *ip)
862{
863 struct gpio_v2_line_values lv;
864 int ret;
865
866 if (copy_from_user(&lv, ip, sizeof(lv)))
867 return -EFAULT;
868
869 mutex_lock(&lr->config_mutex);
870
871 ret = linereq_set_values_unlocked(lr, &lv);
872
873 mutex_unlock(&lr->config_mutex);
874
875 return ret;
876}
877
819static long linereq_set_config_unlocked(struct linereq *lr,
820 struct gpio_v2_line_config *lc)
821{
822 struct gpio_desc *desc;
823 unsigned int i;
824 u64 flags;
825 bool polarity_change;
826 int ret;

--- 60 unchanged lines hidden (view full) ---

887static long linereq_ioctl(struct file *file, unsigned int cmd,
888 unsigned long arg)
889{
890 struct linereq *lr = file->private_data;
891 void __user *ip = (void __user *)arg;
892
893 if (cmd == GPIO_V2_LINE_GET_VALUES_IOCTL)
894 return linereq_get_values(lr, ip);
878static long linereq_set_config_unlocked(struct linereq *lr,
879 struct gpio_v2_line_config *lc)
880{
881 struct gpio_desc *desc;
882 unsigned int i;
883 u64 flags;
884 bool polarity_change;
885 int ret;

--- 60 unchanged lines hidden (view full) ---

946static long linereq_ioctl(struct file *file, unsigned int cmd,
947 unsigned long arg)
948{
949 struct linereq *lr = file->private_data;
950 void __user *ip = (void __user *)arg;
951
952 if (cmd == GPIO_V2_LINE_GET_VALUES_IOCTL)
953 return linereq_get_values(lr, ip);
954 else if (cmd == GPIO_V2_LINE_SET_VALUES_IOCTL)
955 return linereq_set_values(lr, ip);
895 else if (cmd == GPIO_V2_LINE_SET_CONFIG_IOCTL)
896 return linereq_set_config(lr, ip);
897
898 return -EINVAL;
899}
900
901#ifdef CONFIG_COMPAT
902static long linereq_ioctl_compat(struct file *file, unsigned int cmd,

--- 1140 unchanged lines hidden ---
956 else if (cmd == GPIO_V2_LINE_SET_CONFIG_IOCTL)
957 return linereq_set_config(lr, ip);
958
959 return -EINVAL;
960}
961
962#ifdef CONFIG_COMPAT
963static long linereq_ioctl_compat(struct file *file, unsigned int cmd,

--- 1140 unchanged lines hidden ---