mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
qca_spi: Improve reset mechanism
The commit 92717c2356
("net: qca_spi: Avoid high load if QCA7000 is not
available") fixed the high load in case the QCA7000 is not available
but introduced sync delays for some corner cases like buffer errors.
So add the reset requests to the atomics flags, which are polled by
the SPI thread. As a result reset requests and sync state are now
separated. This has the nice benefit to make the code easier to
understand.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://patch.msgid.link/20241007113312.38728-3-wahrenst@gmx.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
234b526896
commit
c81cdba640
@ -98,8 +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 : %lx\n",
|
||||
qca->intr);
|
||||
seq_printf(s, "FLAGS : %lx\n",
|
||||
qca->flags);
|
||||
|
||||
seq_printf(s, "SPI max speed : %lu\n",
|
||||
(unsigned long)qca->spi_dev->max_speed_hz);
|
||||
|
@ -35,7 +35,8 @@
|
||||
|
||||
#define MAX_DMA_BURST_LEN 5000
|
||||
|
||||
#define SPI_INTR 0
|
||||
#define SPI_INTR 0
|
||||
#define SPI_RESET 1
|
||||
|
||||
/* Modules parameters */
|
||||
#define QCASPI_CLK_SPEED_MIN 1000000
|
||||
@ -495,7 +496,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
|
||||
if (qca->sync == QCASPI_SYNC_READY)
|
||||
qca->stats.bad_signature++;
|
||||
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
set_bit(SPI_RESET, &qca->flags);
|
||||
netdev_dbg(qca->net_dev, "sync: got CPU on, but signature was invalid, restart\n");
|
||||
return;
|
||||
} else {
|
||||
@ -512,6 +513,10 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Handle reset only on QCASPI_EVENT_UPDATE */
|
||||
if (test_and_clear_bit(SPI_RESET, &qca->flags))
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
}
|
||||
|
||||
switch (qca->sync) {
|
||||
@ -522,7 +527,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
|
||||
qcaspi_read_register(qca, SPI_REG_SIGNATURE, &signature);
|
||||
|
||||
if (signature != QCASPI_GOOD_SIGNATURE) {
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
set_bit(SPI_RESET, &qca->flags);
|
||||
qca->stats.bad_signature++;
|
||||
netdev_dbg(qca->net_dev, "sync: bad signature, restart\n");
|
||||
/* don't reset right away */
|
||||
@ -553,7 +558,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event)
|
||||
qca->reset_count);
|
||||
if (qca->reset_count >= QCASPI_RESET_TIMEOUT) {
|
||||
/* reset did not seem to take place, try again */
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
set_bit(SPI_RESET, &qca->flags);
|
||||
qca->stats.reset_timeout++;
|
||||
netdev_dbg(qca->net_dev, "sync: reset timeout, restarting process.\n");
|
||||
}
|
||||
@ -582,14 +587,14 @@ qcaspi_spi_thread(void *data)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_bit(SPI_INTR, &qca->intr) &&
|
||||
if (!qca->flags &&
|
||||
!qca->txr.skb[qca->txr.head])
|
||||
schedule();
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
netdev_dbg(qca->net_dev, "have work to do. int: %lu, tx_skb: %p\n",
|
||||
qca->intr,
|
||||
qca->flags,
|
||||
qca->txr.skb[qca->txr.head]);
|
||||
|
||||
qcaspi_qca7k_sync(qca, QCASPI_EVENT_UPDATE);
|
||||
@ -603,7 +608,7 @@ qcaspi_spi_thread(void *data)
|
||||
msleep(QCASPI_QCA7K_REBOOT_TIME_MS);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(SPI_INTR, &qca->intr)) {
|
||||
if (test_and_clear_bit(SPI_INTR, &qca->flags)) {
|
||||
start_spi_intr_handling(qca, &intr_cause);
|
||||
|
||||
if (intr_cause & SPI_INT_CPU_ON) {
|
||||
@ -628,7 +633,7 @@ qcaspi_spi_thread(void *data)
|
||||
/* restart sync */
|
||||
netdev_dbg(qca->net_dev, "===> rdbuf error!\n");
|
||||
qca->stats.read_buf_err++;
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
set_bit(SPI_RESET, &qca->flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -636,7 +641,7 @@ qcaspi_spi_thread(void *data)
|
||||
/* restart sync */
|
||||
netdev_dbg(qca->net_dev, "===> wrbuf error!\n");
|
||||
qca->stats.write_buf_err++;
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
set_bit(SPI_RESET, &qca->flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -665,7 +670,7 @@ qcaspi_intr_handler(int irq, void *data)
|
||||
{
|
||||
struct qcaspi *qca = data;
|
||||
|
||||
set_bit(SPI_INTR, &qca->intr);
|
||||
set_bit(SPI_INTR, &qca->flags);
|
||||
if (qca->spi_thread)
|
||||
wake_up_process(qca->spi_thread);
|
||||
|
||||
@ -681,7 +686,7 @@ qcaspi_netdev_open(struct net_device *dev)
|
||||
if (!qca)
|
||||
return -EINVAL;
|
||||
|
||||
set_bit(SPI_INTR, &qca->intr);
|
||||
set_bit(SPI_INTR, &qca->flags);
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
qcafrm_fsm_init_spi(&qca->frm_handle);
|
||||
|
||||
@ -800,7 +805,7 @@ qcaspi_netdev_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
jiffies, jiffies - dev_trans_start(dev));
|
||||
qca->net_dev->stats.tx_errors++;
|
||||
/* Trigger tx queue flush and QCA7000 reset */
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
set_bit(SPI_RESET, &qca->flags);
|
||||
|
||||
if (qca->spi_thread)
|
||||
wake_up_process(qca->spi_thread);
|
||||
|
@ -81,7 +81,7 @@ struct qcaspi {
|
||||
struct qcafrm_handle frm_handle;
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
unsigned long intr;
|
||||
unsigned long flags;
|
||||
u16 reset_count;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
Loading…
Reference in New Issue
Block a user