drivers/net/ethernet/freescale/enetc/enetc.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/freescale/enetc/enetc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/freescale/enetc/enetc.c
Extension
.c
Size
94689 bytes
Lines
3792
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

enetc_tx_csum_offload_check(skb) && !tx_ring->tsd_enable) {
			temp_bd.l3_aux0 = FIELD_PREP(ENETC_TX_BD_L3_START,
						     skb_network_offset(skb));
			temp_bd.l3_aux1 = FIELD_PREP(ENETC_TX_BD_L3_HDR_LEN,
						     skb_network_header_len(skb) / 4);
			temp_bd.l3_aux1 |= FIELD_PREP(ENETC_TX_BD_L3T,
						      enetc_skb_is_ipv6(skb));
			if (enetc_skb_is_tcp(skb))
				temp_bd.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T,
							    ENETC_TXBD_L4T_TCP);
			else
				temp_bd.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T,
							    ENETC_TXBD_L4T_UDP);
			flags |= ENETC_TXBD_FLAGS_CSUM_LSO | ENETC_TXBD_FLAGS_L4CS;
			csum_offload = true;
		} else if (skb_checksum_help(skb)) {
			return 0;
		}
	}

	if (enetc_cb->flag & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) {
		do_onestep_tstamp = true;
		tstamp = enetc_update_ptp_sync_msg(priv, skb, csum_offload);
	} else if (enetc_cb->flag & ENETC_F_TX_TSTAMP) {
		do_twostep_tstamp = true;
	}

	i = tx_ring->next_to_use;
	txbd = ENETC_TXBD(*tx_ring, i);
	prefetchw(txbd);

	dma = dma_map_single(tx_ring->dev, skb->data, len, DMA_TO_DEVICE);
	if (unlikely(dma_mapping_error(tx_ring->dev, dma)))
		goto dma_err;

	temp_bd.addr = cpu_to_le64(dma);
	temp_bd.buf_len = cpu_to_le16(len);

	tx_swbd = &tx_ring->tx_swbd[i];
	tx_swbd->dma = dma;
	tx_swbd->len = len;
	tx_swbd->is_dma_page = 0;
	tx_swbd->dir = DMA_TO_DEVICE;
	count++;

	do_vlan = skb_vlan_tag_present(skb);
	tx_swbd->do_twostep_tstamp = do_twostep_tstamp;
	tx_swbd->qbv_en = !!(priv->active_offloads & ENETC_F_QBV);
	tx_swbd->check_wb = tx_swbd->do_twostep_tstamp || tx_swbd->qbv_en;

	if (do_vlan || do_onestep_tstamp || do_twostep_tstamp)
		flags |= ENETC_TXBD_FLAGS_EX;

	if (tx_ring->tsd_enable)
		flags |= ENETC_TXBD_FLAGS_TSE | ENETC_TXBD_FLAGS_TXSTART;

	/* first BD needs frm_len and offload flags set */
	temp_bd.frm_len = cpu_to_le16(skb->len);
	temp_bd.flags = flags;

	if (flags & ENETC_TXBD_FLAGS_TSE)
		temp_bd.txstart = enetc_txbd_set_tx_start(skb->skb_mstamp_ns,
							  flags);

	if (flags & ENETC_TXBD_FLAGS_EX) {
		u8 e_flags = 0;
		*txbd = temp_bd;
		enetc_clear_tx_bd(&temp_bd);

		/* add extension BD for VLAN and/or timestamping */
		flags = 0;
		tx_swbd++;
		txbd++;
		i++;
		if (unlikely(i == tx_ring->bd_count)) {
			i = 0;
			tx_swbd = tx_ring->tx_swbd;
			txbd = ENETC_TXBD(*tx_ring, 0);
		}
		prefetchw(txbd);

		if (do_vlan) {
			temp_bd.ext.vid = cpu_to_le16(skb_vlan_tag_get(skb));
			temp_bd.ext.tpid = 0; /* < C-TAG */
			e_flags |= ENETC_TXBD_E_FLAGS_VLAN_INS;
		}

		if (do_onestep_tstamp) {
			/* Configure extension BD */
			temp_bd.ext.tstamp = cpu_to_le32(tstamp);

Annotation

Implementation Notes