On Mon, Aug 31, 2020 at 5:23 AM Kent Gibson <warthog618@xxxxxxxxx> wrote: > > Add support for the GPIO_V2_LINE_SET_VALUES_IOCTL. > > Signed-off-by: Kent Gibson <warthog618@xxxxxxxxx> > --- > drivers/gpio/gpiolib-cdev.c | 59 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 59 insertions(+) > > diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c > index 936b8c9958dd..9f05bbd2161e 100644 > --- a/drivers/gpio/gpiolib-cdev.c > +++ b/drivers/gpio/gpiolib-cdev.c > @@ -777,6 +777,63 @@ static long linereq_get_values(struct linereq *lr, void __user *ip) > return 0; > } > > +static long linereq_set_values_unlocked(struct linereq *lr, > + struct gpio_v2_line_values *lv) > +{ > + DECLARE_BITMAP(vals, GPIO_V2_LINES_MAX); > + struct gpio_desc **descs; > + unsigned int i, didx, num_set; > + int ret; > + > + bitmap_zero(vals, GPIO_V2_LINES_MAX); > + for (num_set = 0, i = 0; i < lr->num_lines; i++) { > + if (lv->mask & BIT_ULL(i)) { > + if (!test_bit(FLAG_IS_OUT, &lr->lines[i].desc->flags)) > + return -EPERM; > + if (lv->bits & BIT_ULL(i)) > + __set_bit(num_set, vals); > + num_set++; > + descs = &lr->lines[i].desc; > + } > + } > + if (num_set == 0) > + return -EINVAL; > + > + if (num_set != 1) { > + /* build compacted desc array and values */ > + descs = kmalloc_array(num_set, sizeof(*descs), GFP_KERNEL); Missing retval check. > + for (didx = 0, i = 0; i < lr->num_lines; i++) { > + if (lv->mask & BIT_ULL(i)) { > + descs[didx] = lr->lines[i].desc; > + didx++; > + } > + } > + } > + ret = gpiod_set_array_value_complex(false, true, num_set, > + descs, NULL, vals); > + > + if (num_set != 1) > + kfree(descs); > + return ret; > +} > + > +static long linereq_set_values(struct linereq *lr, void __user *ip) > +{ > + struct gpio_v2_line_values lv; > + int ret; > + > + if (copy_from_user(&lv, ip, sizeof(lv))) > + return -EFAULT; > + > + mutex_lock(&lr->config_mutex); > + > + ret = linereq_set_values_unlocked(lr, &lv); > + > + mutex_unlock(&lr->config_mutex); > + > + return ret; > +} > + > static long linereq_set_config_unlocked(struct linereq *lr, > struct gpio_v2_line_config *lc) > { > @@ -853,6 +910,8 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, > > if (cmd == GPIO_V2_LINE_GET_VALUES_IOCTL) > return linereq_get_values(lr, ip); > + else if (cmd == GPIO_V2_LINE_SET_VALUES_IOCTL) > + return linereq_set_values(lr, ip); > else if (cmd == GPIO_V2_LINE_SET_CONFIG_IOCTL) > return linereq_set_config(lr, ip); > > -- > 2.28.0 >