Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1596248 > unrolled thread
| Started by | Julia Cartwright <julia@ni.com> |
|---|---|
| First post | 2017-03-09 18:50 +0100 |
| Last post | 2017-03-09 19:10 +0100 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 00/19] fixup usage of non-raw spinlocks in irqchips Julia Cartwright <julia@ni.com> - 2017-03-09 18:50 +0100
[PATCH 13/19] mfd: asic3: make use of raw_spinlock variants Julia Cartwright <julia@ni.com> - 2017-03-09 18:50 +0100
[PATCH 07/19] gpio: bcm-kona: make use of raw_spinlock variants Julia Cartwright <julia@ni.com> - 2017-03-09 19:00 +0100
Re: [PATCH 07/19] gpio: bcm-kona: make use of raw_spinlock variants Ray Jui <ray.jui@broadcom.com> - 2017-03-10 18:30 +0100
Re: [PATCH 07/19] gpio: bcm-kona: make use of raw_spinlock variants Julia Cartwright <julia@ni.com> - 2017-03-10 20:40 +0100
[PATCH 08/19] gpio: etraxfs: make use of raw_spinlock variants Julia Cartwright <julia@ni.com> - 2017-03-09 19:10 +0100
| From | Julia Cartwright <julia@ni.com> |
|---|---|
| Date | 2017-03-09 18:50 +0100 |
| Subject | [PATCH 00/19] fixup usage of non-raw spinlocks in irqchips |
| Message-ID | <tj9gC-7KS-21@gated-at.bofh.it> |
The following patchset introduces a new coccinelle patch,
irq_chip_raw_spinlock.cocci, which is used to identify irq_chip implementors
which acquire/release non-raw spinlocks, and in addition, a set of generated
patches for most cases identified.
On mainline builds, there exists no functional difference between
raw_spinlock_t and spinlock_t. However, w/ PREEMPT_RT, the spinlock_t will
cause the calling thread to sleep when the lock is contended. Because sleeping
is illegal in hardirq context, and because the irqchip callbacks are invoked in
hardirq context, irqchip implementations must not use spin_lock_t for
synchronization.
Patches build tested only.
Some notes:
- In order to ensure that latency problems are not introduced for realtime
kernels, the generated patches need to be hand audited to ensure that
raw-spinlock protected regions are bounded and minimal. I've done a quick
audit for each of the modified drivers in this series, but please check my
work.
- There are a couple of matches which will require further intervention to
fully fix. Namely the Intel LPE Audio driver:
drivers/gpu/drm/i915/intel_lpe_audio.c:169:30-38: Use of non-raw spinlock is illegal in this context (struct drm_i915_private::irq_lock)
and the adi2 pinctrl driver:
drivers/pinctrl/pinctrl-adi2.c:308:26-30: Use of non-raw spinlock is illegal in this context (struct gpio_port::lock)
- This semantic patch is not comprehensive, there are other equally broken
usecases which are not properly identified yet, such as the use of a single
global spinlock_t declared via DEFINE_SPINLOCK() (found in arch/alpha, and
perhaps elsewhere).
Julia
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: Gilles Muller <Gilles.Muller@lip6.fr>
Cc: Nicolas Palix <nicolas.palix@imag.fr>
Cc: Michal Marek <mmarek@suse.com>
Cc: cocci@systeme.lip6.fr
---------
Julia Cartwright (19):
Coccinelle: locks: identify callers of spin_lock{,_irq,_irqsave}() in
irqchip implementations
gpio: altera: make use of raw_spinlock variants
alpha: marvel: make use of raw_spinlock variants
powerpc: mpc52xx_gpt: make use of raw_spinlock variants
gpio: 104-dio-48e: make use of raw_spinlock variants
gpio: ath79: make use of raw_spinlock variants
gpio: bcm-kona: make use of raw_spinlock variants
gpio: etraxfs: make use of raw_spinlock variants
gpio: pl061: make use of raw_spinlock variants
gpio: ws16c48: make use of raw_spinlock variants
gpio: zx: make use of raw_spinlock variants
i2c: mux: pca954x: make use of raw_spinlock variants
mfd: asic3: make use of raw_spinlock variants
mfd: t7l66xb: make use of raw_spinlock variants
mfd: tc6393xb: make use of raw_spinlock variants
pinctrl: bcm: make use of raw_spinlock variants
pinctrl: amd: make use of raw_spinlock variants
pinctrl: sirf: atlas7: make use of raw_spinlock variants
pinctrl: sunxi: make use of raw_spinlock variants
arch/alpha/include/asm/core_marvel.h | 2 +-
arch/alpha/kernel/sys_marvel.c | 12 +--
arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 52 ++++++------
drivers/gpio/gpio-104-dio-48e.c | 38 ++++-----
drivers/gpio/gpio-altera.c | 24 +++---
drivers/gpio/gpio-ath79.c | 28 +++----
drivers/gpio/gpio-bcm-kona.c | 48 +++++------
drivers/gpio/gpio-etraxfs.c | 24 +++---
drivers/gpio/gpio-pl061.c | 28 +++----
drivers/gpio/gpio-ws16c48.c | 46 +++++------
drivers/gpio/gpio-zx.c | 24 +++---
drivers/i2c/muxes/i2c-mux-pca954x.c | 12 +--
drivers/mfd/asic3.c | 56 ++++++-------
drivers/mfd/t7l66xb.c | 20 ++---
drivers/mfd/tc6393xb.c | 52 ++++++------
drivers/pinctrl/bcm/pinctrl-iproc-gpio.c | 44 +++++-----
drivers/pinctrl/bcm/pinctrl-nsp-gpio.c | 46 +++++------
drivers/pinctrl/pinctrl-amd.c | 66 +++++++--------
drivers/pinctrl/pinctrl-amd.h | 2 +-
drivers/pinctrl/sirf/pinctrl-atlas7.c | 44 +++++-----
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 26 +++---
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 +-
.../coccinelle/locks/irq_chip_raw_spinlock.cocci | 96 ++++++++++++++++++++++
23 files changed, 444 insertions(+), 348 deletions(-)
create mode 100644 scripts/coccinelle/locks/irq_chip_raw_spinlock.cocci
--
2.11.1
[toc] | [next] | [standalone]
| From | Julia Cartwright <julia@ni.com> |
|---|---|
| Date | 2017-03-09 18:50 +0100 |
| Subject | [PATCH 13/19] mfd: asic3: make use of raw_spinlock variants |
| Message-ID | <tjamm-8rP-15@gated-at.bofh.it> |
| In reply to | #1596248 |
The asic3 mfd driver currently implements an irq_chip for handling
interrupts; due to how irq_chip handling is done, it's necessary for the
irq_chip methods to be invoked from hardirq context, even on a a
real-time kernel. Because the spinlock_t type becomes a "sleeping"
spinlock w/ RT kernels, it is not suitable to be used with irq_chips.
A quick audit of the operations under the lock reveal that they do only
minimal, bounded work, and are therefore safe to do under a raw spinlock.
Signed-off-by: Julia Cartwright <julia@ni.com>
---
drivers/mfd/asic3.c | 56 ++++++++++++++++++++++++++---------------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 0413c8159551..cf2e25ab2940 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -78,7 +78,7 @@ struct asic3 {
unsigned int bus_shift;
unsigned int irq_nr;
unsigned int irq_base;
- spinlock_t lock;
+ raw_spinlock_t lock;
u16 irq_bothedge[4];
struct gpio_chip gpio;
struct device *dev;
@@ -108,14 +108,14 @@ static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
unsigned long flags;
u32 val;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
val = asic3_read_register(asic, reg);
if (set)
val |= bits;
else
val &= ~bits;
asic3_write_register(asic, reg, val);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
/* IRQs */
@@ -129,13 +129,13 @@ static void asic3_irq_flip_edge(struct asic3 *asic,
u16 edge;
unsigned long flags;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
edge = asic3_read_register(asic,
base + ASIC3_GPIO_EDGE_TRIGGER);
edge ^= bit;
asic3_write_register(asic,
base + ASIC3_GPIO_EDGE_TRIGGER, edge);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static void asic3_irq_demux(struct irq_desc *desc)
@@ -151,10 +151,10 @@ static void asic3_irq_demux(struct irq_desc *desc)
u32 status;
int bank;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
status = asic3_read_register(asic,
ASIC3_OFFSET(INTR, P_INT_STAT));
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
/* Check all ten register bits */
if ((status & 0x3ff) == 0)
@@ -167,7 +167,7 @@ static void asic3_irq_demux(struct irq_desc *desc)
base = ASIC3_GPIO_A_BASE
+ bank * ASIC3_GPIO_BASE_INCR;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
istat = asic3_read_register(asic,
base +
ASIC3_GPIO_INT_STATUS);
@@ -175,7 +175,7 @@ static void asic3_irq_demux(struct irq_desc *desc)
asic3_write_register(asic,
base +
ASIC3_GPIO_INT_STATUS, 0);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) {
int bit = (1 << i);
@@ -230,11 +230,11 @@ static void asic3_mask_gpio_irq(struct irq_data *data)
bank = asic3_irq_to_bank(asic, data->irq);
index = asic3_irq_to_index(asic, data->irq);
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
val |= 1 << index;
asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static void asic3_mask_irq(struct irq_data *data)
@@ -243,7 +243,7 @@ static void asic3_mask_irq(struct irq_data *data)
int regval;
unsigned long flags;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
regval = asic3_read_register(asic,
ASIC3_INTR_BASE +
ASIC3_INTR_INT_MASK);
@@ -255,7 +255,7 @@ static void asic3_mask_irq(struct irq_data *data)
ASIC3_INTR_BASE +
ASIC3_INTR_INT_MASK,
regval);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static void asic3_unmask_gpio_irq(struct irq_data *data)
@@ -267,11 +267,11 @@ static void asic3_unmask_gpio_irq(struct irq_data *data)
bank = asic3_irq_to_bank(asic, data->irq);
index = asic3_irq_to_index(asic, data->irq);
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
val &= ~(1 << index);
asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static void asic3_unmask_irq(struct irq_data *data)
@@ -280,7 +280,7 @@ static void asic3_unmask_irq(struct irq_data *data)
int regval;
unsigned long flags;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
regval = asic3_read_register(asic,
ASIC3_INTR_BASE +
ASIC3_INTR_INT_MASK);
@@ -292,7 +292,7 @@ static void asic3_unmask_irq(struct irq_data *data)
ASIC3_INTR_BASE +
ASIC3_INTR_INT_MASK,
regval);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
@@ -306,7 +306,7 @@ static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
index = asic3_irq_to_index(asic, data->irq);
bit = 1<<index;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
level = asic3_read_register(asic,
bank + ASIC3_GPIO_LEVEL_TRIGGER);
edge = asic3_read_register(asic,
@@ -348,7 +348,7 @@ static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
edge);
asic3_write_register(asic, bank + ASIC3_GPIO_TRIGGER_TYPE,
trigger);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
return 0;
}
@@ -455,7 +455,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip,
return -EINVAL;
}
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_DIRECTION);
@@ -467,7 +467,7 @@ static int asic3_gpio_direction(struct gpio_chip *chip,
asic3_write_register(asic, gpio_base + ASIC3_GPIO_DIRECTION, out_reg);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
return 0;
@@ -524,7 +524,7 @@ static void asic3_gpio_set(struct gpio_chip *chip,
mask = ASIC3_GPIO_TO_MASK(offset);
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_OUT);
@@ -535,7 +535,7 @@ static void asic3_gpio_set(struct gpio_chip *chip,
asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg);
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -611,13 +611,13 @@ static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
unsigned long flags;
u32 cdex;
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
if (clk->enabled++ == 0) {
cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
cdex |= clk->cdex;
asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
}
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
@@ -627,13 +627,13 @@ static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
WARN_ON(clk->enabled == 0);
- spin_lock_irqsave(&asic->lock, flags);
+ raw_spin_lock_irqsave(&asic->lock, flags);
if (--clk->enabled == 0) {
cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
cdex &= ~clk->cdex;
asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
}
- spin_unlock_irqrestore(&asic->lock, flags);
+ raw_spin_unlock_irqrestore(&asic->lock, flags);
}
/* MFD cells (SPI, PWM, LED, DS1WM, MMC) */
@@ -963,7 +963,7 @@ static int __init asic3_probe(struct platform_device *pdev)
if (!asic)
return -ENOMEM;
- spin_lock_init(&asic->lock);
+ raw_spin_lock_init(&asic->lock);
platform_set_drvdata(pdev, asic);
asic->dev = &pdev->dev;
--
2.11.1
[toc] | [prev] | [next] | [standalone]
| From | Julia Cartwright <julia@ni.com> |
|---|---|
| Date | 2017-03-09 19:00 +0100 |
| Subject | [PATCH 07/19] gpio: bcm-kona: make use of raw_spinlock variants |
| Message-ID | <tjaw2-8vb-9@gated-at.bofh.it> |
| In reply to | #1596248 |
The bcm-kona gpio driver currently implements an irq_chip for handling
interrupts; due to how irq_chip handling is done, it's necessary for the
irq_chip methods to be invoked from hardirq context, even on a a
real-time kernel. Because the spinlock_t type becomes a "sleeping"
spinlock w/ RT kernels, it is not suitable to be used with irq_chips.
A quick audit of the operations under the lock reveal that they do only
minimal, bounded work, and are therefore safe to do under a raw spinlock.
Signed-off-by: Julia Cartwright <julia@ni.com>
---
drivers/gpio/gpio-bcm-kona.c | 48 ++++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 41d0ac142580..dfcf56ee3c61 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -67,7 +67,7 @@
struct bcm_kona_gpio {
void __iomem *reg_base;
int num_bank;
- spinlock_t lock;
+ raw_spinlock_t lock;
struct gpio_chip gpio_chip;
struct irq_domain *irq_domain;
struct bcm_kona_gpio_bank *banks;
@@ -95,13 +95,13 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
val |= BIT(gpio);
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
@@ -111,13 +111,13 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
val &= ~BIT(gpio);
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
@@ -141,7 +141,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
/* this function only applies to output pin */
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
@@ -154,7 +154,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
writel(val, reg_base + reg_offset);
out:
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
@@ -168,7 +168,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
reg_offset = GPIO_IN_STATUS(bank_id);
@@ -178,7 +178,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
/* read the GPIO bank status */
val = readl(reg_base + reg_offset);
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
/* return the specified bit status */
return !!(val & BIT(bit));
@@ -208,14 +208,14 @@ static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
writel(val, reg_base + GPIO_CONTROL(gpio));
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@@ -232,7 +232,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
@@ -244,7 +244,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
val |= BIT(bit);
writel(val, reg_base + reg_offset);
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@@ -288,7 +288,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
}
/* spin lock for read-modify-write of the GPIO register */
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_DBR_MASK;
@@ -303,7 +303,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
writel(val, reg_base + GPIO_CONTROL(gpio));
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@@ -347,13 +347,13 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_INT_STATUS(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_STATUS(bank_id));
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_irq_mask(struct irq_data *d)
@@ -368,13 +368,13 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_INT_MASK(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_MASK(bank_id));
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
@@ -389,13 +389,13 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@@ -431,14 +431,14 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- spin_lock_irqsave(&kona_gpio->lock, flags);
+ raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_ITR_MASK;
val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
writel(val, reg_base + GPIO_CONTROL(gpio));
- spin_unlock_irqrestore(&kona_gpio->lock, flags);
+ raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@@ -655,7 +655,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
bank);
}
- spin_lock_init(&kona_gpio->lock);
+ raw_spin_lock_init(&kona_gpio->lock);
return 0;
--
2.11.1
[toc] | [prev] | [next] | [standalone]
| From | Ray Jui <ray.jui@broadcom.com> |
|---|---|
| Date | 2017-03-10 18:30 +0100 |
| Subject | Re: [PATCH 07/19] gpio: bcm-kona: make use of raw_spinlock variants |
| Message-ID | <tjwwy-79v-17@gated-at.bofh.it> |
| In reply to | #1596264 |
Hi Julia/Linus,
On 3/9/2017 8:21 AM, Julia Cartwright wrote:
> The bcm-kona gpio driver currently implements an irq_chip for handling
> interrupts; due to how irq_chip handling is done, it's necessary for the
> irq_chip methods to be invoked from hardirq context, even on a a
> real-time kernel. Because the spinlock_t type becomes a "sleeping"
> spinlock w/ RT kernels, it is not suitable to be used with irq_chips.
>
> A quick audit of the operations under the lock reveal that they do only
> minimal, bounded work, and are therefore safe to do under a raw spinlock.
This is new to me. But it seems like, for the vast majority cases, user
can still continue to use spin_lock as it is without needing to worry
about the underlying difference between standard or RT kernels. But in
certain cases, e.g., irq_chips, extra care needs to be done, i.e.,
switching to use raw spin lock to make sure that it is not blocking in
the case of RT.
Is such API use change well accepted by the open source community already?
Thanks,
Ray
>
> Signed-off-by: Julia Cartwright <julia@ni.com>
> ---
> drivers/gpio/gpio-bcm-kona.c | 48 ++++++++++++++++++++++----------------------
> 1 file changed, 24 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
> index 41d0ac142580..dfcf56ee3c61 100644
> --- a/drivers/gpio/gpio-bcm-kona.c
> +++ b/drivers/gpio/gpio-bcm-kona.c
> @@ -67,7 +67,7 @@
> struct bcm_kona_gpio {
> void __iomem *reg_base;
> int num_bank;
> - spinlock_t lock;
> + raw_spinlock_t lock;
> struct gpio_chip gpio_chip;
> struct irq_domain *irq_domain;
> struct bcm_kona_gpio_bank *banks;
> @@ -95,13 +95,13 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
> unsigned long flags;
> int bank_id = GPIO_BANK(gpio);
>
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
> val |= BIT(gpio);
> bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
> }
>
> static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
> @@ -111,13 +111,13 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
> unsigned long flags;
> int bank_id = GPIO_BANK(gpio);
>
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
> val &= ~BIT(gpio);
> bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
> }
>
> static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
> @@ -141,7 +141,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
>
> kona_gpio = gpiochip_get_data(chip);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> /* this function only applies to output pin */
> if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
> @@ -154,7 +154,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
> writel(val, reg_base + reg_offset);
>
> out:
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
> }
>
> static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
> @@ -168,7 +168,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
>
> kona_gpio = gpiochip_get_data(chip);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
> reg_offset = GPIO_IN_STATUS(bank_id);
> @@ -178,7 +178,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
> /* read the GPIO bank status */
> val = readl(reg_base + reg_offset);
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
>
> /* return the specified bit status */
> return !!(val & BIT(bit));
> @@ -208,14 +208,14 @@ static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
>
> kona_gpio = gpiochip_get_data(chip);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_CONTROL(gpio));
> val &= ~GPIO_GPCTR0_IOTR_MASK;
> val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
> writel(val, reg_base + GPIO_CONTROL(gpio));
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
>
> return 0;
> }
> @@ -232,7 +232,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
>
> kona_gpio = gpiochip_get_data(chip);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_CONTROL(gpio));
> val &= ~GPIO_GPCTR0_IOTR_MASK;
> @@ -244,7 +244,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
> val |= BIT(bit);
> writel(val, reg_base + reg_offset);
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
>
> return 0;
> }
> @@ -288,7 +288,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
> }
>
> /* spin lock for read-modify-write of the GPIO register */
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_CONTROL(gpio));
> val &= ~GPIO_GPCTR0_DBR_MASK;
> @@ -303,7 +303,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
>
> writel(val, reg_base + GPIO_CONTROL(gpio));
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
>
> return 0;
> }
> @@ -347,13 +347,13 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
>
> kona_gpio = irq_data_get_irq_chip_data(d);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_INT_STATUS(bank_id));
> val |= BIT(bit);
> writel(val, reg_base + GPIO_INT_STATUS(bank_id));
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
> }
>
> static void bcm_kona_gpio_irq_mask(struct irq_data *d)
> @@ -368,13 +368,13 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
>
> kona_gpio = irq_data_get_irq_chip_data(d);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_INT_MASK(bank_id));
> val |= BIT(bit);
> writel(val, reg_base + GPIO_INT_MASK(bank_id));
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
> }
>
> static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
> @@ -389,13 +389,13 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
>
> kona_gpio = irq_data_get_irq_chip_data(d);
> reg_base = kona_gpio->reg_base;
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
> val |= BIT(bit);
> writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
> }
>
> static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
> @@ -431,14 +431,14 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
> return -EINVAL;
> }
>
> - spin_lock_irqsave(&kona_gpio->lock, flags);
> + raw_spin_lock_irqsave(&kona_gpio->lock, flags);
>
> val = readl(reg_base + GPIO_CONTROL(gpio));
> val &= ~GPIO_GPCTR0_ITR_MASK;
> val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
> writel(val, reg_base + GPIO_CONTROL(gpio));
>
> - spin_unlock_irqrestore(&kona_gpio->lock, flags);
> + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
>
> return 0;
> }
> @@ -655,7 +655,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
> bank);
> }
>
> - spin_lock_init(&kona_gpio->lock);
> + raw_spin_lock_init(&kona_gpio->lock);
>
> return 0;
>
>
[toc] | [prev] | [next] | [standalone]
| From | Julia Cartwright <julia@ni.com> |
|---|---|
| Date | 2017-03-10 20:40 +0100 |
| Subject | Re: [PATCH 07/19] gpio: bcm-kona: make use of raw_spinlock variants |
| Message-ID | <tjyyl-8vc-1@gated-at.bofh.it> |
| In reply to | #1597971 |
[Multipart message — attachments visible in raw view] — view raw
On Fri, Mar 10, 2017 at 09:28:08AM -0800, Ray Jui wrote: > Hi Julia/Linus, > > On 3/9/2017 8:21 AM, Julia Cartwright wrote: > > The bcm-kona gpio driver currently implements an irq_chip for handling > > interrupts; due to how irq_chip handling is done, it's necessary for the > > irq_chip methods to be invoked from hardirq context, even on a a > > real-time kernel. Because the spinlock_t type becomes a "sleeping" > > spinlock w/ RT kernels, it is not suitable to be used with irq_chips. > > > > A quick audit of the operations under the lock reveal that they do only > > minimal, bounded work, and are therefore safe to do under a raw spinlock. > > This is new to me. But it seems like, for the vast majority cases, user > can still continue to use spin_lock as it is without needing to worry > about the underlying difference between standard or RT kernels. If by "user" you mean, "driver developer", then yes. For most driver authors, the distinction between raw and non-raw spinlocks is irrelevant, they can use spinlocks and everything will work out just fine w/ mainline and on RT. > But in certain cases, e.g., irq_chips, extra care needs to be done, > i.e., swtching to use raw spin lock to make sure that it is not > blocking in the case of RT. Correct, on RT the goal is to push as much as possible into a preemptible context, including driver interrupts, etc. However, there are still codepaths which necessarily need to be executed in hardirq context, including anything necessary to support scheduling. This includes: interrupt-dispatching (irq_chips), timers, and the scheduler itself, which is why this "core" code must use the raw spinlock variants. > Is such API use change well accepted by the open source community > already? In what way is this an API change? The API isn't changing, what's changing in this patch is to fix what is an irq_chip implementation which is _currently broken_ on RT. Julia
[toc] | [prev] | [next] | [standalone]
| From | Julia Cartwright <julia@ni.com> |
|---|---|
| Date | 2017-03-09 19:10 +0100 |
| Subject | [PATCH 08/19] gpio: etraxfs: make use of raw_spinlock variants |
| Message-ID | <tjaFH-ma-5@gated-at.bofh.it> |
| In reply to | #1596248 |
The etraxfs gpio driver currently implements an irq_chip for handling
interrupts; due to how irq_chip handling is done, it's necessary for the
irq_chip methods to be invoked from hardirq context, even on a a
real-time kernel. Because the spinlock_t type becomes a "sleeping"
spinlock w/ RT kernels, it is not suitable to be used with irq_chips.
A quick audit of the operations under the lock reveal that they do only
minimal, bounded work, and are therefore safe to do under a raw spinlock.
Signed-off-by: Julia Cartwright <julia@ni.com>
---
drivers/gpio/gpio-etraxfs.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c
index a254d5b07b94..14c6aac26780 100644
--- a/drivers/gpio/gpio-etraxfs.c
+++ b/drivers/gpio/gpio-etraxfs.c
@@ -54,7 +54,7 @@
struct etraxfs_gpio_info;
struct etraxfs_gpio_block {
- spinlock_t lock;
+ raw_spinlock_t lock;
u32 mask;
u32 cfg;
u32 pins;
@@ -233,10 +233,10 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d)
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
- spin_lock(&block->lock);
+ raw_spin_lock(&block->lock);
block->mask &= ~BIT(grpirq);
writel(block->mask, block->regs + block->info->rw_intr_mask);
- spin_unlock(&block->lock);
+ raw_spin_unlock(&block->lock);
}
static void etraxfs_gpio_irq_unmask(struct irq_data *d)
@@ -246,10 +246,10 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d)
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
- spin_lock(&block->lock);
+ raw_spin_lock(&block->lock);
block->mask |= BIT(grpirq);
writel(block->mask, block->regs + block->info->rw_intr_mask);
- spin_unlock(&block->lock);
+ raw_spin_unlock(&block->lock);
}
static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
@@ -280,11 +280,11 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
return -EINVAL;
}
- spin_lock(&block->lock);
+ raw_spin_lock(&block->lock);
block->cfg &= ~(0x7 << (grpirq * 3));
block->cfg |= (cfg << (grpirq * 3));
writel(block->cfg, block->regs + block->info->rw_intr_cfg);
- spin_unlock(&block->lock);
+ raw_spin_unlock(&block->lock);
return 0;
}
@@ -297,7 +297,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
int ret = -EBUSY;
- spin_lock(&block->lock);
+ raw_spin_lock(&block->lock);
if (block->group[grpirq])
goto out;
@@ -316,7 +316,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
}
out:
- spin_unlock(&block->lock);
+ raw_spin_unlock(&block->lock);
return ret;
}
@@ -327,10 +327,10 @@ static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
- spin_lock(&block->lock);
+ raw_spin_lock(&block->lock);
block->group[grpirq] = 0;
gpiochip_unlock_as_irq(&chip->gc, d->hwirq);
- spin_unlock(&block->lock);
+ raw_spin_unlock(&block->lock);
}
static struct irq_chip etraxfs_gpio_irq_chip = {
@@ -391,7 +391,7 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
if (!block)
return -ENOMEM;
- spin_lock_init(&block->lock);
+ raw_spin_lock_init(&block->lock);
block->regs = regs;
block->info = info;
--
2.11.1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web