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:
parent
4f76885213
commit
97e0652f23
3 changed files with 11 additions and 14 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue