Commit c7fe19ed authored by Bartosz Golaszewski's avatar Bartosz Golaszewski
Browse files

gpio: adnp: use lock guards for the I2C lock

Reduce the code complexity by using automatic lock guards with the I2C
mutex.

Link: https://lore.kernel.org/r/20250306-gpiochip-set-conversion-v2-1-a76e72e21425@linaro.org


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
parent 46056010
Loading
Loading
Loading
Loading
+48 −72
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 * Copyright (C) 2011-2012 Avionic Design GmbH
 */

#include <linux/cleanup.h>
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@@ -102,9 +103,9 @@ static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
	struct adnp *adnp = gpiochip_get_data(chip);

	mutex_lock(&adnp->i2c_lock);
	guard(mutex)(&adnp->i2c_lock);

	__adnp_gpio_set(adnp, offset, value);
	mutex_unlock(&adnp->i2c_lock);
}

static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -115,32 +116,26 @@ static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
	u8 value;
	int err;

	mutex_lock(&adnp->i2c_lock);
	guard(mutex)(&adnp->i2c_lock);

	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
	if (err < 0)
		goto out;
		return err;

	value &= ~BIT(pos);

	err = adnp_write(adnp, GPIO_DDR(adnp) + reg, value);
	if (err < 0)
		goto out;
		return err;

	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
	if (err < 0)
		goto out;

	if (value & BIT(pos)) {
		err = -EPERM;
		goto out;
	}
		return err;

	err = 0;
	if (value & BIT(pos))
		return -EPERM;

out:
	mutex_unlock(&adnp->i2c_lock);
	return err;
	return 0;
}

static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
@@ -152,33 +147,28 @@ static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
	int err;
	u8 val;

	mutex_lock(&adnp->i2c_lock);
	guard(mutex)(&adnp->i2c_lock);

	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
	if (err < 0)
		goto out;
		return err;

	val |= BIT(pos);

	err = adnp_write(adnp, GPIO_DDR(adnp) + reg, val);
	if (err < 0)
		goto out;
		return err;

	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
	if (err < 0)
		goto out;
		return err;

	if (!(val & BIT(pos))) {
		err = -EPERM;
		goto out;
	}
	if (!(val & BIT(pos)))
		return -EPERM;

	__adnp_gpio_set(adnp, offset, value);
	err = 0;

out:
	mutex_unlock(&adnp->i2c_lock);
	return err;
	return 0;
}

static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
@@ -188,27 +178,26 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
	int err;

	for (i = 0; i < num_regs; i++) {
		u8 ddr, plr, ier, isr;

		mutex_lock(&adnp->i2c_lock);
		u8 ddr = 0, plr = 0, ier = 0, isr = 0;

		scoped_guard(mutex, &adnp->i2c_lock) {
			err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr);
			if (err < 0)
			goto unlock;
				return;

			err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr);
			if (err < 0)
			goto unlock;
				return;

			err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
			if (err < 0)
			goto unlock;
				return;

			err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
			if (err < 0)
			goto unlock;
				return;

		mutex_unlock(&adnp->i2c_lock);
		}

		for (j = 0; j < 8; j++) {
			unsigned int bit = (i << adnp->reg_shift) + j;
@@ -233,11 +222,6 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
				   direction, level, interrupt, pending);
		}
	}

	return;

unlock:
	mutex_unlock(&adnp->i2c_lock);
}

static irqreturn_t adnp_irq(int irq, void *data)
@@ -249,32 +233,24 @@ static irqreturn_t adnp_irq(int irq, void *data)

	for (i = 0; i < num_regs; i++) {
		unsigned int base = i << adnp->reg_shift, bit;
		u8 changed, level, isr, ier;
		u8 changed, level = 0, isr = 0, ier = 0;
		unsigned long pending;
		int err;

		mutex_lock(&adnp->i2c_lock);

		scoped_guard(mutex, &adnp->i2c_lock) {
			err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
		if (err < 0) {
			mutex_unlock(&adnp->i2c_lock);
			if (err < 0)
				continue;
		}

			err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
		if (err < 0) {
			mutex_unlock(&adnp->i2c_lock);
			if (err < 0)
				continue;
		}

			err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
		if (err < 0) {
			mutex_unlock(&adnp->i2c_lock);
			if (err < 0)
				continue;
		}

		mutex_unlock(&adnp->i2c_lock);

		/* determine pins that changed levels */
		changed = level ^ adnp->irq_level[i];

@@ -366,12 +342,12 @@ static void adnp_irq_bus_unlock(struct irq_data *d)
	struct adnp *adnp = gpiochip_get_data(gc);
	unsigned int num_regs = 1 << adnp->reg_shift, i;

	mutex_lock(&adnp->i2c_lock);

	scoped_guard(mutex, &adnp->i2c_lock) {
		for (i = 0; i < num_regs; i++)
		adnp_write(adnp, GPIO_IER(adnp) + i, adnp->irq_enable[i]);
			adnp_write(adnp, GPIO_IER(adnp) + i,
				   adnp->irq_enable[i]);
	}

	mutex_unlock(&adnp->i2c_lock);
	mutex_unlock(&adnp->irq_lock);
}