summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/gpio-aggregator.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c
index 424a3d25350b..dfd8a4876a27 100644
--- a/drivers/gpio/gpio-aggregator.c
+++ b/drivers/gpio/gpio-aggregator.c
@@ -333,20 +333,14 @@ static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset)
return gpiod_get_value(fwd->descs[offset]);
}
-static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
unsigned long *bits)
{
- struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
- unsigned long *values, flags = 0;
struct gpio_desc **descs;
+ unsigned long *values;
unsigned int i, j = 0;
int error;
- if (chip->can_sleep)
- mutex_lock(&fwd->mlock);
- else
- spin_lock_irqsave(&fwd->slock, flags);
-
/* Both values bitmap and desc pointers are stored in tmp[] */
values = &fwd->tmp[0];
descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)];
@@ -356,16 +350,32 @@ static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask,
descs[j++] = fwd->descs[i];
error = gpiod_get_array_value(j, descs, NULL, values);
- if (!error) {
- j = 0;
- for_each_set_bit(i, mask, fwd->chip.ngpio)
- __assign_bit(i, bits, test_bit(j++, values));
- }
+ if (error)
+ return error;
- if (chip->can_sleep)
+ j = 0;
+ for_each_set_bit(i, mask, fwd->chip.ngpio)
+ __assign_bit(i, bits, test_bit(j++, values));
+
+ return 0;
+}
+
+static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
+ unsigned long flags;
+ int error;
+
+ if (chip->can_sleep) {
+ mutex_lock(&fwd->mlock);
+ error = gpio_fwd_get_multiple(fwd, mask, bits);
mutex_unlock(&fwd->mlock);
- else
+ } else {
+ spin_lock_irqsave(&fwd->slock, flags);
+ error = gpio_fwd_get_multiple(fwd, mask, bits);
spin_unlock_irqrestore(&fwd->slock, flags);
+ }
return error;
}
@@ -377,19 +387,13 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
gpiod_set_value(fwd->descs[offset], value);
}
-static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
unsigned long *bits)
{
- struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
- unsigned long *values, flags = 0;
struct gpio_desc **descs;
+ unsigned long *values;
unsigned int i, j = 0;
- if (chip->can_sleep)
- mutex_lock(&fwd->mlock);
- else
- spin_lock_irqsave(&fwd->slock, flags);
-
/* Both values bitmap and desc pointers are stored in tmp[] */
values = &fwd->tmp[0];
descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)];
@@ -400,11 +404,23 @@ static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask,
}
gpiod_set_array_value(j, descs, NULL, values);
+}
- if (chip->can_sleep)
+static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
+ unsigned long flags;
+
+ if (chip->can_sleep) {
+ mutex_lock(&fwd->mlock);
+ gpio_fwd_set_multiple(fwd, mask, bits);
mutex_unlock(&fwd->mlock);
- else
+ } else {
+ spin_lock_irqsave(&fwd->slock, flags);
+ gpio_fwd_set_multiple(fwd, mask, bits);
spin_unlock_irqrestore(&fwd->slock, flags);
+ }
}
static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset,
@@ -470,9 +486,9 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
chip->direction_input = gpio_fwd_direction_input;
chip->direction_output = gpio_fwd_direction_output;
chip->get = gpio_fwd_get;
- chip->get_multiple = gpio_fwd_get_multiple;
+ chip->get_multiple = gpio_fwd_get_multiple_locked;
chip->set = gpio_fwd_set;
- chip->set_multiple = gpio_fwd_set_multiple;
+ chip->set_multiple = gpio_fwd_set_multiple_locked;
chip->base = -1;
chip->ngpio = ngpios;
fwd->descs = descs;