[PATCH 1/5] gpio: thunderx: avoid potential deadlock

From: Piyush Malgujar
Date: Wed Apr 27 2022 - 10:47:07 EST


Using irqsave/irqrestore locking variants to avoid any deadlock.

Signed-off-by: Piyush Malgujar <pmalgujar@xxxxxxxxxxx>
---
drivers/gpio/gpio-thunderx.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c
index 9f66deab46eaa99d05413a996b585284c433574d..bb2b40e4033b00134af35592b6b7c7f83cf6c737 100644
--- a/drivers/gpio/gpio-thunderx.c
+++ b/drivers/gpio/gpio-thunderx.c
@@ -104,16 +104,17 @@ static int thunderx_gpio_request(struct gpio_chip *chip, unsigned int line)
static int thunderx_gpio_dir_in(struct gpio_chip *chip, unsigned int line)
{
struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
+ unsigned long flags;

if (!thunderx_gpio_is_gpio(txgpio, line))
return -EIO;

- raw_spin_lock(&txgpio->lock);
+ raw_spin_lock_irqsave(&txgpio->lock, flags);
clear_bit(line, txgpio->invert_mask);
clear_bit(line, txgpio->od_mask);
writeq(txgpio->line_entries[line].fil_bits,
txgpio->register_base + bit_cfg_reg(line));
- raw_spin_unlock(&txgpio->lock);
+ raw_spin_unlock_irqrestore(&txgpio->lock, flags);
return 0;
}

@@ -135,11 +136,12 @@ static int thunderx_gpio_dir_out(struct gpio_chip *chip, unsigned int line,
{
struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
u64 bit_cfg = txgpio->line_entries[line].fil_bits | GPIO_BIT_CFG_TX_OE;
+ unsigned long flags;

if (!thunderx_gpio_is_gpio(txgpio, line))
return -EIO;

- raw_spin_lock(&txgpio->lock);
+ raw_spin_lock_irqsave(&txgpio->lock, flags);

thunderx_gpio_set(chip, line, value);

@@ -151,7 +153,7 @@ static int thunderx_gpio_dir_out(struct gpio_chip *chip, unsigned int line,

writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line));

- raw_spin_unlock(&txgpio->lock);
+ raw_spin_unlock_irqrestore(&txgpio->lock, flags);
return 0;
}

@@ -188,11 +190,12 @@ static int thunderx_gpio_set_config(struct gpio_chip *chip,
int ret = -ENOTSUPP;
struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
void __iomem *reg = txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET;
+ unsigned long flags;

if (!thunderx_gpio_is_gpio(txgpio, line))
return -EIO;

- raw_spin_lock(&txgpio->lock);
+ raw_spin_lock_irqsave(&txgpio->lock, flags);
orig_invert = test_bit(line, txgpio->invert_mask);
new_invert = orig_invert;
orig_od = test_bit(line, txgpio->od_mask);
@@ -243,7 +246,7 @@ static int thunderx_gpio_set_config(struct gpio_chip *chip,
default:
break;
}
- raw_spin_unlock(&txgpio->lock);
+ raw_spin_unlock_irqrestore(&txgpio->lock, flags);

/*
* If currently output and OPEN_DRAIN changed, install the new
@@ -329,6 +332,7 @@ static int thunderx_gpio_irq_set_type(struct irq_data *d,
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
struct thunderx_line *txline =
&txgpio->line_entries[irqd_to_hwirq(d)];
+ unsigned long flags;
u64 bit_cfg;

irqd_set_trigger_type(d, flow_type);
@@ -342,7 +346,7 @@ static int thunderx_gpio_irq_set_type(struct irq_data *d,
irq_set_handler_locked(d, handle_fasteoi_mask_irq);
}

- raw_spin_lock(&txgpio->lock);
+ raw_spin_lock_irqsave(&txgpio->lock, flags);
if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) {
bit_cfg |= GPIO_BIT_CFG_PIN_XOR;
set_bit(txline->line, txgpio->invert_mask);
@@ -351,7 +355,7 @@ static int thunderx_gpio_irq_set_type(struct irq_data *d,
}
clear_bit(txline->line, txgpio->od_mask);
writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(txline->line));
- raw_spin_unlock(&txgpio->lock);
+ raw_spin_unlock_irqrestore(&txgpio->lock, flags);

return IRQ_SET_MASK_OK;
}
--
2.17.1