drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
Extension
.c
Size
41164 bytes
Lines
1585
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (timestamp != 1) {
			timestamp = pfvf->ptp->convert_tx_ptp_tstmp(timestamp);
			err = otx2_ptp_tstamp2time(pfvf, timestamp, &tsns);
			if (!err) {
				memset(&ts, 0, sizeof(ts));
				ts.hwtstamp = ns_to_ktime(tsns);
				skb_tstamp_tx(skb, &ts);
			}
		}
	}

	*tx_bytes += skb->len;
	(*tx_pkts)++;
	otx2_dma_unmap_skb_frags(pfvf, sg);
	napi_consume_skb(skb, budget);
	sg->skb = (u64)NULL;
}

static void otx2_set_rxtstamp(struct otx2_nic *pfvf,
			      struct sk_buff *skb, void *data)
{
	u64 timestamp, tsns;
	int err;

	if (!(pfvf->flags & OTX2_FLAG_RX_TSTAMP_ENABLED))
		return;

	timestamp = pfvf->ptp->convert_rx_ptp_tstmp(*(u64 *)data);
	/* The first 8 bytes is the timestamp */
	err = otx2_ptp_tstamp2time(pfvf, timestamp, &tsns);
	if (err)
		return;

	skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(tsns);
}

static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
			      u64 iova, int len, struct nix_rx_parse_s *parse,
			      int qidx)
{
	struct page *page;
	int off = 0;
	void *va;

	va = phys_to_virt(otx2_iova_to_phys(pfvf->iommu_domain, iova));

	if (likely(!skb_shinfo(skb)->nr_frags)) {
		/* Check if data starts at some nonzero offset
		 * from the start of the buffer.  For now the
		 * only possible offset is 8 bytes in the case
		 * where packet is prepended by a timestamp.
		 */
		if (parse->laptr) {
			otx2_set_rxtstamp(pfvf, skb, va);
			off = OTX2_HW_TIMESTAMP_LEN;
		}
	}

	page = virt_to_page(va);
	if (likely(skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS)) {
		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
				va - page_address(page) + off,
				len - off, pfvf->rbsize);
		return true;
	}

	/* If more than MAX_SKB_FRAGS fragments are received then
	 * give back those buffer pointers to hardware for reuse.
	 */
	pfvf->hw_ops->aura_freeptr(pfvf, qidx, iova & ~0x07ULL);

	return false;
}

static void otx2_set_rxhash(struct otx2_nic *pfvf,
			    struct nix_cqe_rx_s *cqe, struct sk_buff *skb)
{
	enum pkt_hash_types hash_type = PKT_HASH_TYPE_NONE;
	struct otx2_rss_info *rss;
	u32 hash = 0;

	if (!(pfvf->netdev->features & NETIF_F_RXHASH))
		return;

	rss = &pfvf->hw.rss_info;
	if (rss->flowkey_cfg) {
		if (rss->flowkey_cfg &
		    ~(NIX_FLOW_KEY_TYPE_IPV4 | NIX_FLOW_KEY_TYPE_IPV6))
			hash_type = PKT_HASH_TYPE_L4;
		else

Annotation

Implementation Notes