Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbdc9e68 authored by Aviad Krawczyk's avatar Aviad Krawczyk Committed by David S. Miller
Browse files

net-next/hinic: Fix a case of Tx Queue is Stopped forever



Fix the following scenario:
1. tx_free_poll is running on cpu X
2. xmit function is running on cpu Y and fails to get sq wqe
3. tx_free_poll frees wqes on cpu X and checks the queue is not stopped
4. xmit function stops the queue after failed to get sq wqe
5. The queue is stopped forever

Signed-off-by: default avatarAviad Krawczyk <aviad.krawczyk@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 352f58b0
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -212,10 +212,19 @@ netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)

	sq_wqe = hinic_sq_get_wqe(txq->sq, wqe_size, &prod_idx);
	if (!sq_wqe) {
		tx_unmap_skb(nic_dev, skb, txq->sges);

		netif_stop_subqueue(netdev, qp->q_id);

		/* Check for the case free_tx_poll is called in another cpu
		 * and we stopped the subqueue after free_tx_poll check.
		 */
		sq_wqe = hinic_sq_get_wqe(txq->sq, wqe_size, &prod_idx);
		if (sq_wqe) {
			netif_wake_subqueue(nic_dev->netdev, qp->q_id);
			goto process_sq_wqe;
		}

		tx_unmap_skb(nic_dev, skb, txq->sges);

		u64_stats_update_begin(&txq->txq_stats.syncp);
		txq->txq_stats.tx_busy++;
		u64_stats_update_end(&txq->txq_stats.syncp);
@@ -223,6 +232,7 @@ netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
		goto flush_skbs;
	}

process_sq_wqe:
	hinic_sq_prepare_wqe(txq->sq, prod_idx, sq_wqe, txq->sges, nr_sges);

	hinic_sq_write_wqe(txq->sq, prod_idx, sq_wqe, skb, wqe_size);