Commit 90d130aa authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'fixes-on-the-open-alliance-tc6-10base-t1x-mac-phy-support-generic-lib'

Parthiban Veerasooran says:

====================
Fixes on the OPEN Alliance TC6 10BASE-T1x MAC-PHY support generic lib

This patch series contain the below fixes.

- Infinite loop error when tx credits becomes 0.
- Race condition between tx skb reference pointers.

v2:
- Added mutex lock to protect tx skb reference handling.

v3:
- Added mutex protection in assigning new tx skb to waiting_tx_skb
  pointer.
- Explained the possible scenario for the race condition with the time
  diagram in the commit message.

v4:
- Replaced mutex with spin_lock_bh() variants as the start_xmit runs in
  BH/softirq context which can't take sleeping locks.
====================

Link: https://patch.msgid.link/20241213123159.439739-1-parthiban.veerasooran@microchip.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 94901b7a e592b511
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ struct oa_tc6 {
	struct mii_bus *mdiobus;
	struct spi_device *spi;
	struct mutex spi_ctrl_lock; /* Protects spi control transfer */
	spinlock_t tx_skb_lock; /* Protects tx skb handling */
	void *spi_ctrl_tx_buf;
	void *spi_ctrl_rx_buf;
	void *spi_data_tx_buf;
@@ -1004,8 +1005,10 @@ static u16 oa_tc6_prepare_spi_tx_buf_for_tx_skbs(struct oa_tc6 *tc6)
	for (used_tx_credits = 0; used_tx_credits < tc6->tx_credits;
	     used_tx_credits++) {
		if (!tc6->ongoing_tx_skb) {
			spin_lock_bh(&tc6->tx_skb_lock);
			tc6->ongoing_tx_skb = tc6->waiting_tx_skb;
			tc6->waiting_tx_skb = NULL;
			spin_unlock_bh(&tc6->tx_skb_lock);
		}
		if (!tc6->ongoing_tx_skb)
			break;
@@ -1111,8 +1114,9 @@ static int oa_tc6_spi_thread_handler(void *data)
		/* This kthread will be waken up if there is a tx skb or mac-phy
		 * interrupt to perform spi transfer with tx chunks.
		 */
		wait_event_interruptible(tc6->spi_wq, tc6->waiting_tx_skb ||
					 tc6->int_flag ||
		wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
					 (tc6->waiting_tx_skb &&
					 tc6->tx_credits) ||
					 kthread_should_stop());

		if (kthread_should_stop())
@@ -1209,7 +1213,9 @@ netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
		return NETDEV_TX_OK;
	}

	spin_lock_bh(&tc6->tx_skb_lock);
	tc6->waiting_tx_skb = skb;
	spin_unlock_bh(&tc6->tx_skb_lock);

	/* Wake spi kthread to perform spi transfer */
	wake_up_interruptible(&tc6->spi_wq);
@@ -1239,6 +1245,7 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
	tc6->netdev = netdev;
	SET_NETDEV_DEV(netdev, &spi->dev);
	mutex_init(&tc6->spi_ctrl_lock);
	spin_lock_init(&tc6->tx_skb_lock);

	/* Set the SPI controller to pump at realtime priority */
	tc6->spi->rt = true;