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: 291ab06ecf ("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>
This commit is contained in:
Stefan Wahren 2024-06-14 16:50:30 +02:00 committed by Paolo Abeni
parent ff960f9d3e
commit 2d7198278e
3 changed files with 11 additions and 14 deletions

View file

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

View file

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

View file

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