drivers/net/ethernet/cavium/thunder/nicvf_main.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/cavium/thunder/nicvf_main.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/cavium/thunder/nicvf_main.c
Extension
.c
Size
60508 bytes
Lines
2331
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 nicvf_netdev_ops = {
	.ndo_open		= nicvf_open,
	.ndo_stop		= nicvf_stop,
	.ndo_start_xmit		= nicvf_xmit,
	.ndo_change_mtu		= nicvf_change_mtu,
	.ndo_set_mac_address	= nicvf_set_mac_address,
	.ndo_get_stats64	= nicvf_get_stats64,
	.ndo_tx_timeout         = nicvf_tx_timeout,
	.ndo_fix_features       = nicvf_fix_features,
	.ndo_set_features       = nicvf_set_features,
	.ndo_bpf		= nicvf_xdp,
	.ndo_set_rx_mode        = nicvf_set_rx_mode,
	.ndo_hwtstamp_get	= nicvf_hwtstamp_get,
	.ndo_hwtstamp_set	= nicvf_hwtstamp_set,
};

static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct device *dev = &pdev->dev;
	struct net_device *netdev;
	struct nicvf *nic;
	int    err, qcount;
	u16    sdevid;
	struct cavium_ptp *ptp_clock;

	ptp_clock = cavium_ptp_get();
	if (IS_ERR(ptp_clock)) {
		if (PTR_ERR(ptp_clock) == -ENODEV)
			/* In virtualized environment we proceed without ptp */
			ptp_clock = NULL;
		else
			return PTR_ERR(ptp_clock);
	}

	err = pci_enable_device(pdev);
	if (err) {
		err = dev_err_probe(dev, err, "Failed to enable PCI device\n");
		goto err_put_ptp;
	}

	err = pci_request_regions(pdev, DRV_NAME);
	if (err) {
		dev_err(dev, "PCI request regions failed 0x%x\n", err);
		goto err_disable_device;
	}

	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
	if (err) {
		dev_err(dev, "Unable to get usable DMA configuration\n");
		goto err_release_regions;
	}

	qcount = netif_get_num_default_rss_queues();

	/* Restrict multiqset support only for host bound VFs */
	if (pdev->is_virtfn) {
		/* Set max number of queues per VF */
		qcount = min_t(int, num_online_cpus(),
			       (MAX_SQS_PER_VF + 1) * MAX_CMP_QUEUES_PER_QS);
	}

	netdev = alloc_etherdev_mqs(sizeof(struct nicvf), qcount, qcount);
	if (!netdev) {
		err = -ENOMEM;
		goto err_release_regions;
	}

	pci_set_drvdata(pdev, netdev);

	SET_NETDEV_DEV(netdev, &pdev->dev);

	nic = netdev_priv(netdev);
	nic->netdev = netdev;
	nic->pdev = pdev;
	nic->pnicvf = nic;
	nic->max_queues = qcount;
	/* If no of CPUs are too low, there won't be any queues left
	 * for XDP_TX, hence double it.
	 */
	if (!nic->t88)
		nic->max_queues *= 2;
	nic->ptp_clock = ptp_clock;

	/* Initialize mutex that serializes usage of VF's mailbox */
	mutex_init(&nic->rx_mode_mtx);

	/* MAP VF's configuration registers */
	nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
	if (!nic->reg_base) {
		dev_err(dev, "Cannot map config register space, aborting\n");

Annotation

Implementation Notes