Commit 2d719827 authored by Stefan Wahren's avatar Stefan Wahren Committed by Paolo Abeni

qca_spi: Make interrupt remembering atomic

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: 291ab06e ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
Signed-off-by: default avatarStefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20240614145030.7781-1-wahrenst@gmx.netSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent ff960f9d
...@@ -98,10 +98,8 @@ qcaspi_info_show(struct seq_file *s, void *what) ...@@ -98,10 +98,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);
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,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
...@@ -579,14 +581,14 @@ qcaspi_spi_thread(void *data) ...@@ -579,14 +581,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);
...@@ -600,8 +602,7 @@ qcaspi_spi_thread(void *data) ...@@ -600,8 +602,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) {
...@@ -663,7 +664,7 @@ qcaspi_intr_handler(int irq, void *data) ...@@ -663,7 +664,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)
wake_up_process(qca->spi_thread); wake_up_process(qca->spi_thread);
...@@ -679,8 +680,7 @@ qcaspi_netdev_open(struct net_device *dev) ...@@ -679,8 +680,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);
......
...@@ -81,8 +81,7 @@ struct qcaspi { ...@@ -81,8 +81,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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment