drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c
Extension
.c
Size
9372 bytes
Lines
342
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 sparx5_port_netdev_ops = {
	.ndo_open               = sparx5_port_open,
	.ndo_stop               = sparx5_port_stop,
	.ndo_start_xmit         = sparx5_port_xmit_impl,
	.ndo_set_rx_mode        = sparx5_set_rx_mode,
	.ndo_get_phys_port_name = sparx5_port_get_phys_port_name,
	.ndo_set_mac_address    = sparx5_set_mac_address,
	.ndo_validate_addr      = eth_validate_addr,
	.ndo_get_stats64        = sparx5_get_stats64,
	.ndo_get_port_parent_id = sparx5_get_port_parent_id,
	.ndo_eth_ioctl          = phy_do_ioctl,
	.ndo_setup_tc           = sparx5_port_setup_tc,
	.ndo_hwtstamp_get       = sparx5_port_hwtstamp_get,
	.ndo_hwtstamp_set       = sparx5_port_hwtstamp_set,
};

bool sparx5_netdevice_check(const struct net_device *dev)
{
	return dev && (dev->netdev_ops == &sparx5_port_netdev_ops);
}

struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno)
{
	struct sparx5_port *spx5_port;
	struct net_device *ndev;

	ndev = devm_alloc_etherdev_mqs(sparx5->dev, sizeof(struct sparx5_port),
				       SPX5_PRIOS, 1);
	if (!ndev)
		return ERR_PTR(-ENOMEM);

	ndev->hw_features |= NETIF_F_HW_TC;
	ndev->features |= NETIF_F_HW_TC;

	SET_NETDEV_DEV(ndev, sparx5->dev);
	spx5_port = netdev_priv(ndev);
	spx5_port->ndev = ndev;
	spx5_port->sparx5 = sparx5;
	spx5_port->portno = portno;

	ndev->netdev_ops = &sparx5_port_netdev_ops;
	ndev->ethtool_ops = &sparx5_ethtool_ops;

	eth_hw_addr_gen(ndev, sparx5->base_mac, portno + 1);

	return ndev;
}

int sparx5_register_netdevs(struct sparx5 *sparx5)
{
	int portno;
	int err;

	for (portno = 0; portno < sparx5->data->consts->n_ports; portno++)
		if (sparx5->ports[portno]) {
			err = register_netdev(sparx5->ports[portno]->ndev);
			if (err) {
				dev_err(sparx5->dev,
					"port: %02u: netdev registration failed\n",
					portno);
				return err;
			}
			sparx5_port_inj_timer_setup(sparx5->ports[portno]);
		}
	return 0;
}

void sparx5_destroy_netdevs(struct sparx5 *sparx5)
{
	struct sparx5_port *port;
	int portno;

	for (portno = 0; portno < sparx5->data->consts->n_ports; portno++) {
		port = sparx5->ports[portno];
		if (port && port->phylink) {
			/* Disconnect the phy */
			rtnl_lock();
			sparx5_port_stop(port->ndev);
			phylink_disconnect_phy(port->phylink);
			rtnl_unlock();
			phylink_destroy(port->phylink);
			port->phylink = NULL;
		}
	}
}

void sparx5_unregister_netdevs(struct sparx5 *sparx5)
{
	int portno;

Annotation

Implementation Notes