summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-dw.h
diff options
context:
space:
mode:
authorwuxu.wu <wuxu.wu@huawei.com>2020-01-01 04:39:41 +0100
committerMark Brown <broonie@kernel.org>2020-01-03 01:59:40 +0100
commit19b61392c5a852b4e8a0bf35aecb969983c5932d (patch)
treeea43e3a3d0498d517ea7c6b7a9c3d70c2bcb4b8e /drivers/spi/spi-dw.h
parentspi: spi-fsl-dspi: Fix 16-bit word order in 32-bit XSPI mode (diff)
downloadlinux-19b61392c5a852b4e8a0bf35aecb969983c5932d.tar.xz
linux-19b61392c5a852b4e8a0bf35aecb969983c5932d.zip
spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls
dw_spi_irq() and dw_spi_transfer_one concurrent calls. I find a panic in dw_writer(): txw = *(u8 *)(dws->tx), when dw->tx==null, dw->len==4, and dw->tx_end==1. When tpm driver's message overtime dw_spi_irq() and dw_spi_transfer_one may concurrent visit dw_spi, so I think dw_spi structure lack of protection. Otherwise dw_spi_transfer_one set dw rx/tx buffer and then open irq, store dw rx/tx instructions and other cores handle irq load dw rx/tx instructions may out of order. [ 1025.321302] Call trace: ... [ 1025.321319] __crash_kexec+0x98/0x148 [ 1025.321323] panic+0x17c/0x314 [ 1025.321329] die+0x29c/0x2e8 [ 1025.321334] die_kernel_fault+0x68/0x78 [ 1025.321337] __do_kernel_fault+0x90/0xb0 [ 1025.321346] do_page_fault+0x88/0x500 [ 1025.321347] do_translation_fault+0xa8/0xb8 [ 1025.321349] do_mem_abort+0x68/0x118 [ 1025.321351] el1_da+0x20/0x8c [ 1025.321362] dw_writer+0xc8/0xd0 [ 1025.321364] interrupt_transfer+0x60/0x110 [ 1025.321365] dw_spi_irq+0x48/0x70 ... Signed-off-by: wuxu.wu <wuxu.wu@huawei.com> Link: https://lore.kernel.org/r/1577849981-31489-1-git-send-email-wuxu.wu@huawei.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-dw.h')
-rw-r--r--drivers/spi/spi-dw.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 38c7de1f0aa9..1bf5713e047d 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -119,6 +119,7 @@ struct dw_spi {
size_t len;
void *tx;
void *tx_end;
+ spinlock_t buf_lock;
void *rx;
void *rx_end;
int dma_mapped;