qca_spi: Make interrupt remembering atomic

[ Upstream commit 2d7198278ece01818cd95a3beffbdf8b2a353fa0 ]

The whole mechanism to remember occurred SPI interrupts is not atomic,
which could lead to unexpected behavior. So fix this by using atomic bit
operations instead.

Fixes: 291ab06ecf67 ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20240614145030.7781-1-wahrenst@gmx.net
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Stefan Wahren 2024-06-14 16:50:30 +02:00 committed by Ksawlii
parent 4f76885213
commit 97e0652f23
3 changed files with 11 additions and 14 deletions

View file

@ -110,10 +110,8 @@ qcaspi_info_show(struct seq_file *s, void *what)
seq_printf(s, "IRQ : %d\n", seq_printf(s, "IRQ : %d\n",
qca->spi_dev->irq); qca->spi_dev->irq);
seq_printf(s, "INTR REQ : %u\n", seq_printf(s, "INTR : %lx\n",
qca->intr_req); qca->intr);
seq_printf(s, "INTR SVC : %u\n",
qca->intr_svc);
seq_printf(s, "SPI max speed : %lu\n", seq_printf(s, "SPI max speed : %lu\n",
(unsigned long)qca->spi_dev->max_speed_hz); (unsigned long)qca->spi_dev->max_speed_hz);

View file

@ -49,6 +49,8 @@
#define MAX_DMA_BURST_LEN 5000 #define MAX_DMA_BURST_LEN 5000
#define SPI_INTR 0
/* Modules parameters */ /* Modules parameters */
#define QCASPI_CLK_SPEED_MIN 1000000 #define QCASPI_CLK_SPEED_MIN 1000000
#define QCASPI_CLK_SPEED_MAX 16000000 #define QCASPI_CLK_SPEED_MAX 16000000
@ -585,14 +587,14 @@ qcaspi_spi_thread(void *data)
continue; continue;
} }
if ((qca->intr_req == qca->intr_svc) && if (!test_bit(SPI_INTR, &qca->intr) &&
!qca->txr.skb[qca->txr.head]) !qca->txr.skb[qca->txr.head])
schedule(); schedule();
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
netdev_dbg(qca->net_dev, "have work to do. int: %d, tx_skb: %p\n", netdev_dbg(qca->net_dev, "have work to do. int: %lu, tx_skb: %p\n",
qca->intr_req - qca->intr_svc, qca->intr,
qca->txr.skb[qca->txr.head]); qca->txr.skb[qca->txr.head]);
qcaspi_qca7k_sync(qca, QCASPI_EVENT_UPDATE); qcaspi_qca7k_sync(qca, QCASPI_EVENT_UPDATE);
@ -606,8 +608,7 @@ qcaspi_spi_thread(void *data)
msleep(QCASPI_QCA7K_REBOOT_TIME_MS); msleep(QCASPI_QCA7K_REBOOT_TIME_MS);
} }
if (qca->intr_svc != qca->intr_req) { if (test_and_clear_bit(SPI_INTR, &qca->intr)) {
qca->intr_svc = qca->intr_req;
start_spi_intr_handling(qca, &intr_cause); start_spi_intr_handling(qca, &intr_cause);
if (intr_cause & SPI_INT_CPU_ON) { if (intr_cause & SPI_INT_CPU_ON) {
@ -669,7 +670,7 @@ qcaspi_intr_handler(int irq, void *data)
{ {
struct qcaspi *qca = data; struct qcaspi *qca = data;
qca->intr_req++; set_bit(SPI_INTR, &qca->intr);
if (qca->spi_thread && if (qca->spi_thread &&
qca->spi_thread->state != TASK_RUNNING) qca->spi_thread->state != TASK_RUNNING)
wake_up_process(qca->spi_thread); wake_up_process(qca->spi_thread);
@ -686,8 +687,7 @@ qcaspi_netdev_open(struct net_device *dev)
if (!qca) if (!qca)
return -EINVAL; return -EINVAL;
qca->intr_req = 1; set_bit(SPI_INTR, &qca->intr);
qca->intr_svc = 0;
qca->sync = QCASPI_SYNC_UNKNOWN; qca->sync = QCASPI_SYNC_UNKNOWN;
qcafrm_fsm_init_spi(&qca->frm_handle); qcafrm_fsm_init_spi(&qca->frm_handle);

View file

@ -92,8 +92,7 @@ struct qcaspi {
struct qcafrm_handle frm_handle; struct qcafrm_handle frm_handle;
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
unsigned int intr_req; unsigned long intr;
unsigned int intr_svc;
u16 reset_count; u16 reset_count;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS