drivers/net/ethernet/intel/igc/igc_main.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/igc/igc_main.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/igc/igc_main.c
Extension
.c
Size
205930 bytes
Lines
7874
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops igc_netdev_ops = {
	.ndo_open		= igc_open,
	.ndo_stop		= igc_close,
	.ndo_start_xmit		= igc_xmit_frame,
	.ndo_set_rx_mode	= igc_set_rx_mode,
	.ndo_set_mac_address	= igc_set_mac,
	.ndo_change_mtu		= igc_change_mtu,
	.ndo_tx_timeout		= igc_tx_timeout,
	.ndo_get_stats64	= igc_get_stats64,
	.ndo_fix_features	= igc_fix_features,
	.ndo_set_features	= igc_set_features,
	.ndo_features_check	= igc_features_check,
	.ndo_setup_tc		= igc_setup_tc,
	.ndo_bpf		= igc_bpf,
	.ndo_xdp_xmit		= igc_xdp_xmit,
	.ndo_xsk_wakeup		= igc_xsk_wakeup,
	.ndo_get_tstamp		= igc_get_tstamp,
	.ndo_hwtstamp_get	= igc_ptp_hwtstamp_get,
	.ndo_hwtstamp_set	= igc_ptp_hwtstamp_set,
};

u32 igc_rd32(struct igc_hw *hw, u32 reg)
{
	struct igc_adapter *igc = container_of(hw, struct igc_adapter, hw);
	u8 __iomem *hw_addr = READ_ONCE(hw->hw_addr);
	u32 value = 0;

	if (IGC_REMOVED(hw_addr))
		return ~value;

	value = readl(&hw_addr[reg]);

	/* reads should not return all F's */
	if (!(~value) && (!reg || !(~readl(hw_addr)))) {
		struct net_device *netdev = igc->netdev;

		hw->hw_addr = NULL;
		netif_device_detach(netdev);
		netdev_err(netdev, "PCIe link lost, device now detached\n");
		WARN(pci_device_is_present(igc->pdev),
		     "igc: Failed to read reg 0x%x!\n", reg);
	}

	return value;
}

/* Mapping HW RSS Type to enum xdp_rss_hash_type */
static enum xdp_rss_hash_type igc_xdp_rss_type[IGC_RSS_TYPE_MAX_TABLE] = {
	[IGC_RSS_TYPE_NO_HASH]		= XDP_RSS_TYPE_L2,
	[IGC_RSS_TYPE_HASH_TCP_IPV4]	= XDP_RSS_TYPE_L4_IPV4_TCP,
	[IGC_RSS_TYPE_HASH_IPV4]	= XDP_RSS_TYPE_L3_IPV4,
	[IGC_RSS_TYPE_HASH_TCP_IPV6]	= XDP_RSS_TYPE_L4_IPV6_TCP,
	[IGC_RSS_TYPE_HASH_IPV6_EX]	= XDP_RSS_TYPE_L3_IPV6_EX,
	[IGC_RSS_TYPE_HASH_IPV6]	= XDP_RSS_TYPE_L3_IPV6,
	[IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_TCP_EX,
	[IGC_RSS_TYPE_HASH_UDP_IPV4]	= XDP_RSS_TYPE_L4_IPV4_UDP,
	[IGC_RSS_TYPE_HASH_UDP_IPV6]	= XDP_RSS_TYPE_L4_IPV6_UDP,
	[IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_UDP_EX,
	[10] = XDP_RSS_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW  */
	[11] = XDP_RSS_TYPE_NONE, /* keep array sized for SW bit-mask   */
	[12] = XDP_RSS_TYPE_NONE, /* to handle future HW revisions       */
	[13] = XDP_RSS_TYPE_NONE,
	[14] = XDP_RSS_TYPE_NONE,
	[15] = XDP_RSS_TYPE_NONE,
};

static int igc_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash,
			   enum xdp_rss_hash_type *rss_type)
{
	const struct igc_xdp_buff *ctx = (void *)_ctx;

	if (!(ctx->xdp.rxq->dev->features & NETIF_F_RXHASH))
		return -ENODATA;

	*hash = le32_to_cpu(ctx->rx_desc->wb.lower.hi_dword.rss);
	*rss_type = igc_xdp_rss_type[igc_rss_type(ctx->rx_desc)];

	return 0;
}

static int igc_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp)
{
	const struct igc_xdp_buff *ctx = (void *)_ctx;
	struct igc_adapter *adapter = netdev_priv(ctx->xdp.rxq->dev);
	struct igc_inline_rx_tstamps *tstamp = ctx->rx_ts;

	if (igc_test_staterr(ctx->rx_desc, IGC_RXDADV_STAT_TSIP)) {
		*timestamp = igc_ptp_rx_pktstamp(adapter, tstamp->timer0);

		return 0;

Annotation

Implementation Notes