On Tue, Sep 22, 2020 at 5:36 AM Kent Gibson <warthog618@xxxxxxxxx> wrote: > > Add support for the GPIO_V2_LINE_SET_VALUES_IOCTL. > +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)) { Similar idea DECLARE_BITMAP(mask, 64) = BITMAP_FROM_U64(lv->mask); num_set = bitmap_weight(); for_each_set_bit(i, mask, lr->num_lines) > + 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); > + if (!descs) > + return -ENOMEM; > + 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) > { > @@ -889,6 +948,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 > -- With Best Regards, Andy Shevchenko