Commit 271f31d5 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'qca_spi-collection-of-major-fixes'

Stefan Wahren says:

====================
qca_spi: collection of major fixes

This series contains a collection of major fixes for the qca_spi driver,
which has been recently discovered.
====================

Link: https://lore.kernel.org/r/20231206141222.52029-1-wahrenst@gmx.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents a1664b99 1057812d
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@

#define QCASPI_MAX_REGS 0x20

#define QCASPI_RX_MAX_FRAMES 4

static const u16 qcaspi_spi_regs[] = {
	SPI_REG_BFR_SIZE,
	SPI_REG_WRBUF_SPC_AVA,
@@ -252,9 +254,9 @@ qcaspi_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
{
	struct qcaspi *qca = netdev_priv(dev);

	ring->rx_max_pending = 4;
	ring->rx_max_pending = QCASPI_RX_MAX_FRAMES;
	ring->tx_max_pending = TX_RING_MAX_LEN;
	ring->rx_pending = 4;
	ring->rx_pending = QCASPI_RX_MAX_FRAMES;
	ring->tx_pending = qca->txr.count;
}

@@ -263,22 +265,21 @@ qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
		     struct kernel_ethtool_ringparam *kernel_ring,
		     struct netlink_ext_ack *extack)
{
	const struct net_device_ops *ops = dev->netdev_ops;
	struct qcaspi *qca = netdev_priv(dev);

	if ((ring->rx_pending) ||
	if (ring->rx_pending != QCASPI_RX_MAX_FRAMES ||
	    (ring->rx_mini_pending) ||
	    (ring->rx_jumbo_pending))
		return -EINVAL;

	if (netif_running(dev))
		ops->ndo_stop(dev);
	if (qca->spi_thread)
		kthread_park(qca->spi_thread);

	qca->txr.count = max_t(u32, ring->tx_pending, TX_RING_MIN_LEN);
	qca->txr.count = min_t(u16, qca->txr.count, TX_RING_MAX_LEN);

	if (netif_running(dev))
		ops->ndo_open(dev);
	if (qca->spi_thread)
		kthread_unpark(qca->spi_thread);

	return 0;
}
+19 −1
Original line number Diff line number Diff line
@@ -580,6 +580,18 @@ qcaspi_spi_thread(void *data)
	netdev_info(qca->net_dev, "SPI thread created\n");
	while (!kthread_should_stop()) {
		set_current_state(TASK_INTERRUPTIBLE);
		if (kthread_should_park()) {
			netif_tx_disable(qca->net_dev);
			netif_carrier_off(qca->net_dev);
			qcaspi_flush_tx_ring(qca);
			kthread_parkme();
			if (qca->sync == QCASPI_SYNC_READY) {
				netif_carrier_on(qca->net_dev);
				netif_wake_queue(qca->net_dev);
			}
			continue;
		}

		if ((qca->intr_req == qca->intr_svc) &&
		    !qca->txr.skb[qca->txr.head])
			schedule();
@@ -608,11 +620,17 @@ qcaspi_spi_thread(void *data)
			if (intr_cause & SPI_INT_CPU_ON) {
				qcaspi_qca7k_sync(qca, QCASPI_EVENT_CPUON);

				/* Frame decoding in progress */
				if (qca->frm_handle.state != qca->frm_handle.init)
					qca->net_dev->stats.rx_dropped++;

				qcafrm_fsm_init_spi(&qca->frm_handle);
				qca->stats.device_reset++;

				/* not synced. */
				if (qca->sync != QCASPI_SYNC_READY)
					continue;

				qca->stats.device_reset++;
				netif_wake_queue(qca->net_dev);
				netif_carrier_on(qca->net_dev);
			}