drivers/infiniband/hw/hfi1/ipoib_tx.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/hfi1/ipoib_tx.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/hfi1/ipoib_tx.c
Extension
.c
Size
22826 bytes
Lines
869
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ipoib_txparms {
	struct hfi1_devdata        *dd;
	struct rdma_ah_attr        *ah_attr;
	struct hfi1_ibport         *ibp;
	struct hfi1_ipoib_txq      *txq;
	union hfi1_ipoib_flow       flow;
	u32                         dqpn;
	u8                          hdr_dwords;
	u8                          entropy;
};

static struct ipoib_txreq *
hfi1_txreq_from_idx(struct hfi1_ipoib_circ_buf *r, u32 idx)
{
	return (struct ipoib_txreq *)(r->items + (idx << r->shift));
}

static u32 hfi1_ipoib_txreqs(const u64 sent, const u64 completed)
{
	return sent - completed;
}

static u64 hfi1_ipoib_used(struct hfi1_ipoib_txq *txq)
{
	return hfi1_ipoib_txreqs(txq->tx_ring.sent_txreqs,
				 txq->tx_ring.complete_txreqs);
}

static void hfi1_ipoib_stop_txq(struct hfi1_ipoib_txq *txq)
{
	trace_hfi1_txq_stop(txq);
	if (atomic_inc_return(&txq->tx_ring.stops) == 1)
		netif_stop_subqueue(txq->priv->netdev, txq->q_idx);
}

static void hfi1_ipoib_wake_txq(struct hfi1_ipoib_txq *txq)
{
	trace_hfi1_txq_wake(txq);
	if (atomic_dec_and_test(&txq->tx_ring.stops))
		netif_wake_subqueue(txq->priv->netdev, txq->q_idx);
}

static uint hfi1_ipoib_ring_hwat(struct hfi1_ipoib_txq *txq)
{
	return min_t(uint, txq->priv->netdev->tx_queue_len,
		     txq->tx_ring.max_items - 1);
}

static uint hfi1_ipoib_ring_lwat(struct hfi1_ipoib_txq *txq)
{
	return min_t(uint, txq->priv->netdev->tx_queue_len,
		     txq->tx_ring.max_items) >> 1;
}

static void hfi1_ipoib_check_queue_depth(struct hfi1_ipoib_txq *txq)
{
	++txq->tx_ring.sent_txreqs;
	if (hfi1_ipoib_used(txq) >= hfi1_ipoib_ring_hwat(txq) &&
	    !atomic_xchg(&txq->tx_ring.ring_full, 1)) {
		trace_hfi1_txq_full(txq);
		hfi1_ipoib_stop_txq(txq);
	}
}

static void hfi1_ipoib_check_queue_stopped(struct hfi1_ipoib_txq *txq)
{
	struct net_device *dev = txq->priv->netdev;

	/* If shutting down just return as queue state is irrelevant */
	if (unlikely(dev->reg_state != NETREG_REGISTERED))
		return;

	/*
	 * When the queue has been drained to less than half full it will be
	 * restarted.
	 * The size of the txreq ring is fixed at initialization.
	 * The tx queue len can be adjusted upward while the interface is
	 * running.
	 * The tx queue len can be large enough to overflow the txreq_ring.
	 * Use the minimum of the current tx_queue_len or the rings max txreqs
	 * to protect against ring overflow.
	 */
	if (hfi1_ipoib_used(txq) < hfi1_ipoib_ring_lwat(txq) &&
	    atomic_xchg(&txq->tx_ring.ring_full, 0)) {
		trace_hfi1_txq_xmit_unstopped(txq);
		hfi1_ipoib_wake_txq(txq);
	}
}

static void hfi1_ipoib_free_tx(struct ipoib_txreq *tx, int budget)

Annotation

Implementation Notes