drivers/net/ethernet/huawei/hinic/hinic_tx.c
Source file repositories/reference/linux-study-clean/drivers/net/ethernet/huawei/hinic/hinic_tx.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ethernet/huawei/hinic/hinic_tx.c- Extension
.c- Size
- 23775 bytes
- Lines
- 933
- 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.
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/if_vlan.hlinux/kernel.hlinux/netdevice.hlinux/u64_stats_sync.hlinux/errno.hlinux/types.hlinux/pci.hlinux/device.hlinux/dma-mapping.hlinux/slab.hlinux/interrupt.hlinux/skbuff.hlinux/smp.hasm/byteorder.hlinux/ip.hlinux/tcp.hlinux/sctp.hlinux/ipv6.hnet/ipv6.hnet/checksum.hnet/ip6_checksum.hhinic_common.hhinic_hw_if.hhinic_hw_wqe.hhinic_hw_wq.hhinic_hw_qp.hhinic_hw_dev.hhinic_dev.hhinic_tx.h
Detected Declarations
enum hinic_offload_typefunction hinic_txq_clean_statsfunction hinic_txq_get_statsfunction txq_stats_initfunction tx_map_skbfunction tx_unmap_skbfunction get_inner_l3_l4_typefunction get_inner_l4_infofunction csum_magicfunction offload_tsofunction offload_csumfunction offload_vlanfunction hinic_tx_offloadfunction hinic_lb_xmit_framefunction hinic_xmit_framefunction tx_free_skbfunction free_all_tx_skbsfunction free_tx_pollfunction tx_irqfunction tx_request_irqfunction tx_free_irqfunction hinic_init_txqfunction hinic_clean_txq
Annotated Snippet
if (dma_mapping_error(&pdev->dev, dma_addr)) {
dev_err(&pdev->dev, "Failed to map Tx skb frag\n");
goto err_tx_map;
}
hinic_set_sge(&sges[i + 1], dma_addr, skb_frag_size(frag));
}
return 0;
err_tx_map:
for (j = 0; j < i; j++)
dma_unmap_page(&pdev->dev, hinic_sge_to_dma(&sges[j + 1]),
sges[j + 1].len, DMA_TO_DEVICE);
dma_unmap_single(&pdev->dev, hinic_sge_to_dma(&sges[0]), sges[0].len,
DMA_TO_DEVICE);
return -EFAULT;
}
/**
* tx_unmap_skb - unmap the dma address of the skb
* @nic_dev: nic device
* @skb: the skb
* @sges: the sges that are connected to the skb
**/
static void tx_unmap_skb(struct hinic_dev *nic_dev, struct sk_buff *skb,
struct hinic_sge *sges)
{
struct hinic_hwdev *hwdev = nic_dev->hwdev;
struct hinic_hwif *hwif = hwdev->hwif;
struct pci_dev *pdev = hwif->pdev;
int i;
for (i = 0; i < skb_shinfo(skb)->nr_frags ; i++)
dma_unmap_page(&pdev->dev, hinic_sge_to_dma(&sges[i + 1]),
sges[i + 1].len, DMA_TO_DEVICE);
dma_unmap_single(&pdev->dev, hinic_sge_to_dma(&sges[0]), sges[0].len,
DMA_TO_DEVICE);
}
static void get_inner_l3_l4_type(struct sk_buff *skb, union hinic_l3 *ip,
union hinic_l4 *l4,
enum hinic_offload_type offload_type,
enum hinic_l3_offload_type *l3_type,
u8 *l4_proto)
{
u8 *exthdr;
if (ip->v4->version == 4) {
*l3_type = (offload_type == TX_OFFLOAD_CSUM) ?
IPV4_PKT_NO_CHKSUM_OFFLOAD :
IPV4_PKT_WITH_CHKSUM_OFFLOAD;
*l4_proto = ip->v4->protocol;
} else if (ip->v4->version == 6) {
*l3_type = IPV6_PKT;
exthdr = ip->hdr + sizeof(*ip->v6);
*l4_proto = ip->v6->nexthdr;
if (exthdr != l4->hdr) {
int start = exthdr - skb->data;
__be16 frag_off;
ipv6_skip_exthdr(skb, start, l4_proto, &frag_off);
}
} else {
*l3_type = L3TYPE_UNKNOWN;
*l4_proto = 0;
}
}
static void get_inner_l4_info(struct sk_buff *skb, union hinic_l4 *l4,
enum hinic_offload_type offload_type, u8 l4_proto,
enum hinic_l4_offload_type *l4_offload,
u32 *l4_len, u32 *offset)
{
*l4_offload = OFFLOAD_DISABLE;
*offset = 0;
*l4_len = 0;
switch (l4_proto) {
case IPPROTO_TCP:
*l4_offload = TCP_OFFLOAD_ENABLE;
/* doff in unit of 4B */
*l4_len = l4->tcp->doff * 4;
*offset = *l4_len + TRANSPORT_OFFSET(l4->hdr, skb);
break;
case IPPROTO_UDP:
*l4_offload = UDP_OFFLOAD_ENABLE;
Annotation
- Immediate include surface: `linux/if_vlan.h`, `linux/kernel.h`, `linux/netdevice.h`, `linux/u64_stats_sync.h`, `linux/errno.h`, `linux/types.h`, `linux/pci.h`, `linux/device.h`.
- Detected declarations: `enum hinic_offload_type`, `function hinic_txq_clean_stats`, `function hinic_txq_get_stats`, `function txq_stats_init`, `function tx_map_skb`, `function tx_unmap_skb`, `function get_inner_l3_l4_type`, `function get_inner_l4_info`, `function csum_magic`, `function offload_tso`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.