drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c
Extension
.c
Size
6446 bytes
Lines
241
Domain
Driver Families
Bucket
drivers/net
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

if (!tso.ipv6) {
			struct iphdr *iph = this_hdr + skb_network_offset(skb);

			iph->check = 0;
		}

		dma_sync_single_for_device(&pdev->dev, this_hdr_dma,
					   hdr_len, DMA_TO_DEVICE);

		bd_count = tso_dma_map_count(&map, seg_payload);

		tx_buf = &txr->tx_buf_ring[RING_TX(bp, prod)];
		txbd = &txr->tx_desc_ring[TX_RING(bp, prod)][TX_IDX(prod)];

		tx_buf->skb = skb;
		tx_buf->nr_frags = bd_count;
		tx_buf->is_push = 0;
		tx_buf->is_ts_pkt = 0;

		dma_unmap_addr_set(tx_buf, mapping, this_hdr_dma);
		dma_unmap_len_set(tx_buf, len, 0);

		if (last) {
			tx_buf->is_sw_gso = BNXT_SW_GSO_LAST;
			tso_dma_map_completion_save(&map, &tx_buf->sw_gso_cstate);
		} else {
			tx_buf->is_sw_gso = BNXT_SW_GSO_MID;
		}

		flags = (hdr_len << TX_BD_LEN_SHIFT) |
			TX_BD_TYPE_LONG_TX_BD |
			TX_BD_CNT(2 + bd_count);

		flags |= bnxt_sw_gso_lhint(hdr_len + seg_payload);

		txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
		txbd->tx_bd_haddr = cpu_to_le64(this_hdr_dma);
		txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod,
						   2 + bd_count);

		prod = NEXT_TX(prod);
		bnxt_init_ext_bd(bp, txr, prod, csum,
				 vlan_tag_flags, cfa_action);

		/* set dma_unmap_len on the LAST BD touching each
		 * region. Since completions are in-order, the last segment
		 * completes after all earlier ones, so the unmap is safe.
		 */
		while (tso_dma_map_next(&map, &dma_addr, &chunk_len,
					&mapping_len, seg_payload)) {
			prod = NEXT_TX(prod);
			txbd = &txr->tx_desc_ring[TX_RING(bp, prod)][TX_IDX(prod)];
			tx_buf = &txr->tx_buf_ring[RING_TX(bp, prod)];

			txbd->tx_bd_haddr = cpu_to_le64(dma_addr);
			dma_unmap_addr_set(tx_buf, mapping, dma_addr);
			dma_unmap_len_set(tx_buf, len, 0);
			tx_buf->skb = NULL;
			tx_buf->is_sw_gso = 0;

			if (mapping_len) {
				if (last_unmap_buf) {
					dma_unmap_addr_set(last_unmap_buf,
							   mapping,
							   last_unmap_addr);
					dma_unmap_len_set(last_unmap_buf,
							  len,
							  last_unmap_len);
				}
				last_unmap_addr = dma_addr;
				last_unmap_len = mapping_len;
			}
			last_unmap_buf = tx_buf;

			flags = chunk_len << TX_BD_LEN_SHIFT;
			txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
			txbd->tx_bd_opaque = 0;

			seg_payload -= chunk_len;
		}

		txbd->tx_bd_len_flags_type |=
			cpu_to_le32(TX_BD_FLAGS_PACKET_END);

		prod = NEXT_TX(prod);
	}

	if (last_unmap_buf) {
		dma_unmap_addr_set(last_unmap_buf, mapping, last_unmap_addr);
		dma_unmap_len_set(last_unmap_buf, len, last_unmap_len);

Annotation

Implementation Notes