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

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.net


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent ff960f9d
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -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);
+8 −8
Original line number Diff line number Diff line
@@ -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);

+1 −2
Original line number Diff line number Diff line
@@ -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