drivers/net/ethernet/sfc/siena/efx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/siena/efx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sfc/siena/efx.c
Extension
.c
Size
33935 bytes
Lines
1351
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 efx_netdev_ops = {
	.ndo_open		= efx_net_open,
	.ndo_stop		= efx_net_stop,
	.ndo_get_stats64	= efx_siena_net_stats,
	.ndo_tx_timeout		= efx_siena_watchdog,
	.ndo_start_xmit		= efx_siena_hard_start_xmit,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= efx_ioctl,
	.ndo_change_mtu		= efx_siena_change_mtu,
	.ndo_set_mac_address	= efx_siena_set_mac_address,
	.ndo_set_rx_mode	= efx_siena_set_rx_mode,
	.ndo_set_features	= efx_siena_set_features,
	.ndo_features_check	= efx_siena_features_check,
	.ndo_vlan_rx_add_vid	= efx_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= efx_vlan_rx_kill_vid,
	.ndo_hwtstamp_set	= efx_siena_hwtstamp_set,
	.ndo_hwtstamp_get	= efx_siena_hwtstamp_get,
#ifdef CONFIG_SFC_SIENA_SRIOV
	.ndo_set_vf_mac		= efx_sriov_set_vf_mac,
	.ndo_set_vf_vlan	= efx_sriov_set_vf_vlan,
	.ndo_set_vf_spoofchk	= efx_sriov_set_vf_spoofchk,
	.ndo_get_vf_config	= efx_sriov_get_vf_config,
	.ndo_set_vf_link_state  = efx_sriov_set_vf_link_state,
#endif
	.ndo_get_phys_port_id   = efx_siena_get_phys_port_id,
	.ndo_get_phys_port_name	= efx_siena_get_phys_port_name,
	.ndo_setup_tc		= efx_siena_setup_tc,
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	= efx_siena_filter_rfs,
#endif
	.ndo_xdp_xmit		= efx_xdp_xmit,
	.ndo_bpf		= efx_xdp
};

static int efx_xdp_setup_prog(struct efx_nic *efx, struct bpf_prog *prog)
{
	struct bpf_prog *old_prog;

	if (efx->xdp_rxq_info_failed) {
		netif_err(efx, drv, efx->net_dev,
			  "Unable to bind XDP program due to previous failure of rxq_info\n");
		return -EINVAL;
	}

	if (prog && efx->net_dev->mtu > efx_siena_xdp_max_mtu(efx)) {
		netif_err(efx, drv, efx->net_dev,
			  "Unable to configure XDP with MTU of %d (max: %d)\n",
			  efx->net_dev->mtu, efx_siena_xdp_max_mtu(efx));
		return -EINVAL;
	}

	old_prog = rtnl_dereference(efx->xdp_prog);
	rcu_assign_pointer(efx->xdp_prog, prog);
	/* Release the reference that was originally passed by the caller. */
	if (old_prog)
		bpf_prog_put(old_prog);

	return 0;
}

/* Context: process, rtnl_lock() held. */
static int efx_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
	struct efx_nic *efx = netdev_priv(dev);

	switch (xdp->command) {
	case XDP_SETUP_PROG:
		return efx_xdp_setup_prog(efx, xdp->prog);
	default:
		return -EINVAL;
	}
}

static int efx_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **xdpfs,
			u32 flags)
{
	struct efx_nic *efx = netdev_priv(dev);

	if (!netif_running(dev))
		return -EINVAL;

	return efx_siena_xdp_tx_buffers(efx, n, xdpfs, flags & XDP_XMIT_FLUSH);
}

static void efx_update_name(struct efx_nic *efx)
{
	strcpy(efx->name, efx->net_dev->name);
	efx_siena_mtd_rename(efx);
	efx_siena_set_channel_names(efx);
}

Annotation

Implementation Notes