diff options
author | Patrice Chotard <patrice.chotard@st.com> | 2018-01-12 07:16:08 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-01-17 01:44:14 -0500 |
commit | b888fb6f2a278442933e3bfab70262e9a5365fb3 (patch) | |
tree | 720fd7e55fdd3a8415e9189f922485c726cec07f /drivers/gpio/gpio-stmpe.c | |
parent | a603a2b8d86ee93ee2107da8ca75fd854fd4ff32 (diff) |
gpio: stmpe: i2c transfer are forbiden in atomic context
Move the workaround from stmpe_gpio_irq_unmask() which is executed
in atomic context to stmpe_gpio_irq_sync_unlock() which is not.
It fixes the following issue:
[ 1.500000] BUG: scheduling while atomic: swapper/1/0x00000002
[ 1.500000] CPU: 0 PID: 1 Comm: swapper Not tainted 4.15.0-rc2-00020-gbd4301f-dirty #28
[ 1.520000] Hardware name: STM32 (Device Tree Support)
[ 1.520000] [<0000bfc9>] (unwind_backtrace) from [<0000b347>] (show_stack+0xb/0xc)
[ 1.530000] [<0000b347>] (show_stack) from [<0001fc49>] (__schedule_bug+0x39/0x58)
[ 1.530000] [<0001fc49>] (__schedule_bug) from [<00168211>] (__schedule+0x23/0x2b2)
[ 1.550000] [<00168211>] (__schedule) from [<001684f7>] (schedule+0x57/0x64)
[ 1.550000] [<001684f7>] (schedule) from [<0016a513>] (schedule_timeout+0x137/0x164)
[ 1.550000] [<0016a513>] (schedule_timeout) from [<00168b91>] (wait_for_common+0x8d/0xfc)
[ 1.570000] [<00168b91>] (wait_for_common) from [<00139753>] (stm32f4_i2c_xfer+0xe9/0xfe)
[ 1.580000] [<00139753>] (stm32f4_i2c_xfer) from [<00138545>] (__i2c_transfer+0x111/0x148)
[ 1.590000] [<00138545>] (__i2c_transfer) from [<001385cf>] (i2c_transfer+0x53/0x70)
[ 1.590000] [<001385cf>] (i2c_transfer) from [<001388a5>] (i2c_smbus_xfer+0x12f/0x36e)
[ 1.600000] [<001388a5>] (i2c_smbus_xfer) from [<00138b49>] (i2c_smbus_read_byte_data+0x1f/0x2a)
[ 1.610000] [<00138b49>] (i2c_smbus_read_byte_data) from [<00124fdd>] (__stmpe_reg_read+0xd/0x24)
[ 1.620000] [<00124fdd>] (__stmpe_reg_read) from [<001252b3>] (stmpe_reg_read+0x19/0x24)
[ 1.630000] [<001252b3>] (stmpe_reg_read) from [<0002c4d1>] (unmask_irq+0x17/0x22)
[ 1.640000] [<0002c4d1>] (unmask_irq) from [<0002c57f>] (irq_startup+0x6f/0x78)
[ 1.650000] [<0002c57f>] (irq_startup) from [<0002b7a1>] (__setup_irq+0x319/0x47c)
[ 1.650000] [<0002b7a1>] (__setup_irq) from [<0002bad3>] (request_threaded_irq+0x6b/0xe8)
[ 1.660000] [<0002bad3>] (request_threaded_irq) from [<0002d0b9>] (devm_request_threaded_irq+0x3b/0x6a)
[ 1.670000] [<0002d0b9>] (devm_request_threaded_irq) from [<001446e7>] (mmc_gpiod_request_cd_irq+0x49/0x8a)
[ 1.680000] [<001446e7>] (mmc_gpiod_request_cd_irq) from [<0013d45d>] (mmc_start_host+0x49/0x60)
[ 1.690000] [<0013d45d>] (mmc_start_host) from [<0013e40b>] (mmc_add_host+0x3b/0x54)
[ 1.700000] [<0013e40b>] (mmc_add_host) from [<00148119>] (mmci_probe+0x4d1/0x60c)
[ 1.710000] [<00148119>] (mmci_probe) from [<000f903b>] (amba_probe+0x7b/0xbe)
[ 1.720000] [<000f903b>] (amba_probe) from [<001170e5>] (driver_probe_device+0x169/0x1f8)
[ 1.730000] [<001170e5>] (driver_probe_device) from [<001171b7>] (__driver_attach+0x43/0x5c)
[ 1.740000] [<001171b7>] (__driver_attach) from [<0011618d>] (bus_for_each_dev+0x3d/0x46)
[ 1.740000] [<0011618d>] (bus_for_each_dev) from [<001165cd>] (bus_add_driver+0xcd/0x124)
[ 1.740000] [<001165cd>] (bus_add_driver) from [<00117713>] (driver_register+0x4d/0x7a)
[ 1.760000] [<00117713>] (driver_register) from [<001fc765>] (do_one_initcall+0xbd/0xe8)
[ 1.770000] [<001fc765>] (do_one_initcall) from [<001fc88b>] (kernel_init_freeable+0xfb/0x134)
[ 1.780000] [<001fc88b>] (kernel_init_freeable) from [<00167ee3>] (kernel_init+0x7/0x9c)
[ 1.790000] [<00167ee3>] (kernel_init) from [<00009b65>] (ret_from_fork+0x11/0x2c)
Cc: stable@vger.kernel.org
Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-stmpe.c')
-rw-r--r-- | drivers/gpio/gpio-stmpe.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index e3d048e65339..3b6efce8e681 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
@@ -190,6 +190,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) | |||
190 | }; | 190 | }; |
191 | int i, j; | 191 | int i, j; |
192 | 192 | ||
193 | /* | ||
194 | * STMPE1600: to be able to get IRQ from pins, | ||
195 | * a read must be done on GPMR register, or a write in | ||
196 | * GPSR or GPCR registers | ||
197 | */ | ||
198 | if (stmpe->partnum == STMPE1600) { | ||
199 | stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]); | ||
200 | stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]); | ||
201 | } | ||
202 | |||
193 | for (i = 0; i < CACHE_NR_REGS; i++) { | 203 | for (i = 0; i < CACHE_NR_REGS; i++) { |
194 | /* STMPE801 and STMPE1600 don't have RE and FE registers */ | 204 | /* STMPE801 and STMPE1600 don't have RE and FE registers */ |
195 | if ((stmpe->partnum == STMPE801 || | 205 | if ((stmpe->partnum == STMPE801 || |
@@ -227,21 +237,11 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d) | |||
227 | { | 237 | { |
228 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | 238 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
229 | struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc); | 239 | struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc); |
230 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
231 | int offset = d->hwirq; | 240 | int offset = d->hwirq; |
232 | int regoffset = offset / 8; | 241 | int regoffset = offset / 8; |
233 | int mask = BIT(offset % 8); | 242 | int mask = BIT(offset % 8); |
234 | 243 | ||
235 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; | 244 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; |
236 | |||
237 | /* | ||
238 | * STMPE1600 workaround: to be able to get IRQ from pins, | ||
239 | * a read must be done on GPMR register, or a write in | ||
240 | * GPSR or GPCR registers | ||
241 | */ | ||
242 | if (stmpe->partnum == STMPE1600) | ||
243 | stmpe_reg_read(stmpe, | ||
244 | stmpe->regs[STMPE_IDX_GPMR_LSB + regoffset]); | ||
245 | } | 245 | } |
246 | 246 | ||
247 | static void stmpe_dbg_show_one(struct seq_file *s, | 247 | static void stmpe_dbg_show_one(struct seq_file *s, |