drivers/net/ethernet/huawei/hinic3/hinic3_tx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
Extension
.c
Size
20853 bytes
Lines
798
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 (dma_mapping_error(&pdev->dev, dma_info[idx].dma)) {
			err = -EFAULT;
			goto err_unmap_page;
		}
		dma_info[idx].len = skb_frag_size(frag);

		hinic3_set_buf_desc(buf_desc, dma_info[idx].dma,
				    dma_info[idx].len);
		buf_desc++;
	}

	return 0;

err_unmap_page:
	while (idx > 1) {
		idx--;
		dma_unmap_page(&pdev->dev, dma_info[idx].dma,
			       dma_info[idx].len, DMA_TO_DEVICE);
	}
	dma_unmap_single(&pdev->dev, dma_info[0].dma, dma_info[0].len,
			 DMA_TO_DEVICE);

	return err;
}

static void hinic3_tx_unmap_skb(struct net_device *netdev,
				struct sk_buff *skb,
				struct hinic3_dma_info *dma_info)
{
	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
	struct pci_dev *pdev = nic_dev->pdev;
	int i;

	for (i = 0; i < skb_shinfo(skb)->nr_frags;) {
		i++;
		dma_unmap_page(&pdev->dev,
			       dma_info[i].dma,
			       dma_info[i].len, DMA_TO_DEVICE);
	}

	dma_unmap_single(&pdev->dev, dma_info[0].dma,
			 dma_info[0].len, DMA_TO_DEVICE);
}

static void free_all_tx_skbs(struct net_device *netdev, u32 sq_depth,
			     struct hinic3_tx_info *tx_info_arr)
{
	struct hinic3_tx_info *tx_info;
	u32 idx;

	for (idx = 0; idx < sq_depth; idx++) {
		tx_info = &tx_info_arr[idx];
		if (tx_info->skb) {
			hinic3_tx_unmap_skb(netdev, tx_info->skb,
					    tx_info->dma_info);
			dev_kfree_skb_any(tx_info->skb);
			tx_info->skb = NULL;
		}
	}
}

union hinic3_ip {
	struct iphdr   *v4;
	struct ipv6hdr *v6;
	unsigned char  *hdr;
};

union hinic3_l4 {
	struct tcphdr *tcp;
	struct udphdr *udp;
	unsigned char *hdr;
};

enum hinic3_l3_type {
	HINIC3_L3_UNKNOWN         = 0,
	HINIC3_L3_IP6_PKT         = 1,
	HINIC3_L3_IP4_PKT_NO_CSUM = 2,
	HINIC3_L3_IP4_PKT_CSUM    = 3,
};

enum hinic3_l4_offload_type {
	HINIC3_L4_OFFLOAD_DISABLE = 0,
	HINIC3_L4_OFFLOAD_TCP     = 1,
	HINIC3_L4_OFFLOAD_STCP    = 2,
	HINIC3_L4_OFFLOAD_UDP     = 3,
};

/* initialize l4 offset and offload */
static void get_inner_l4_info(struct sk_buff *skb, union hinic3_l4 *l4,
			      u8 l4_proto, u32 *offset,

Annotation

Implementation Notes