Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: bitbang: Replace spinlock by mutex

chipselect (in the case of spi-gpio: spi_gpio_chipselect, which
calls gpiod_set_raw_value_cansleep) can sleep, so we should not
hold a spinlock while calling it from spi_bitbang_setup.

This issue was introduced by this commit, which converted spi-gpio
to cansleep variants:
d9dda5a191 "spi: spi-gpio: Use 'cansleep' variants to access GPIO"

Replacing the lock variable by a mutex fixes the issue: This is
safe as all instances where the lock is used are called from
contexts that can sleep.

Finally, update spi-ppc4xx and and spi-s3c24xx to use mutex
functions, as they directly hold the lock for similar purpose.

Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Nicolas Boichat and committed by
Mark Brown
c15f6ed3 6ff33f39

+12 -15
+7 -10
drivers/spi/spi-bitbang.c
··· 180 180 { 181 181 struct spi_bitbang_cs *cs = spi->controller_state; 182 182 struct spi_bitbang *bitbang; 183 - unsigned long flags; 184 183 185 184 bitbang = spi_master_get_devdata(spi->master); 186 185 ··· 209 210 */ 210 211 211 212 /* deselect chip (low or high) */ 212 - spin_lock_irqsave(&bitbang->lock, flags); 213 + mutex_lock(&bitbang->lock); 213 214 if (!bitbang->busy) { 214 215 bitbang->chipselect(spi, BITBANG_CS_INACTIVE); 215 216 ndelay(cs->nsecs); 216 217 } 217 - spin_unlock_irqrestore(&bitbang->lock, flags); 218 + mutex_unlock(&bitbang->lock); 218 219 219 220 return 0; 220 221 } ··· 254 255 static int spi_bitbang_prepare_hardware(struct spi_master *spi) 255 256 { 256 257 struct spi_bitbang *bitbang; 257 - unsigned long flags; 258 258 259 259 bitbang = spi_master_get_devdata(spi); 260 260 261 - spin_lock_irqsave(&bitbang->lock, flags); 261 + mutex_lock(&bitbang->lock); 262 262 bitbang->busy = 1; 263 - spin_unlock_irqrestore(&bitbang->lock, flags); 263 + mutex_unlock(&bitbang->lock); 264 264 265 265 return 0; 266 266 } ··· 376 378 static int spi_bitbang_unprepare_hardware(struct spi_master *spi) 377 379 { 378 380 struct spi_bitbang *bitbang; 379 - unsigned long flags; 380 381 381 382 bitbang = spi_master_get_devdata(spi); 382 383 383 - spin_lock_irqsave(&bitbang->lock, flags); 384 + mutex_lock(&bitbang->lock); 384 385 bitbang->busy = 0; 385 - spin_unlock_irqrestore(&bitbang->lock, flags); 386 + mutex_unlock(&bitbang->lock); 386 387 387 388 return 0; 388 389 } ··· 424 427 if (!master || !bitbang->chipselect) 425 428 return -EINVAL; 426 429 427 - spin_lock_init(&bitbang->lock); 430 + mutex_init(&bitbang->lock); 428 431 429 432 if (!master->mode_bits) 430 433 master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
+2 -2
drivers/spi/spi-ppc4xx.c
··· 210 210 if (in_8(&hw->regs->cdm) != cdm) 211 211 out_8(&hw->regs->cdm, cdm); 212 212 213 - spin_lock(&hw->bitbang.lock); 213 + mutex_lock(&hw->bitbang.lock); 214 214 if (!hw->bitbang.busy) { 215 215 hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); 216 216 /* Need to ndelay here? */ 217 217 } 218 - spin_unlock(&hw->bitbang.lock); 218 + mutex_unlock(&hw->bitbang.lock); 219 219 220 220 return 0; 221 221 }
+2 -2
drivers/spi/spi-s3c24xx.c
··· 198 198 if (ret) 199 199 return ret; 200 200 201 - spin_lock(&hw->bitbang.lock); 201 + mutex_lock(&hw->bitbang.lock); 202 202 if (!hw->bitbang.busy) { 203 203 hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); 204 204 /* need to ndelay for 0.5 clocktick ? */ 205 205 } 206 - spin_unlock(&hw->bitbang.lock); 206 + mutex_unlock(&hw->bitbang.lock); 207 207 208 208 return 0; 209 209 }
+1 -1
include/linux/spi/spi_bitbang.h
··· 4 4 #include <linux/workqueue.h> 5 5 6 6 struct spi_bitbang { 7 - spinlock_t lock; 7 + struct mutex lock; 8 8 u8 busy; 9 9 u8 use_dma; 10 10 u8 flags; /* extra spi->mode support */