drivers/net/usb/lan78xx.c

Source file repositories/reference/linux-study-clean/drivers/net/usb/lan78xx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/lan78xx.c
Extension
.c
Size
131236 bytes
Lines
5387
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 lan78xx_netdev_ops = {
	.ndo_open		= lan78xx_open,
	.ndo_stop		= lan78xx_stop,
	.ndo_start_xmit		= lan78xx_start_xmit,
	.ndo_tx_timeout		= lan78xx_tx_timeout,
	.ndo_change_mtu		= lan78xx_change_mtu,
	.ndo_set_mac_address	= lan78xx_set_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= phy_do_ioctl_running,
	.ndo_set_rx_mode	= lan78xx_set_multicast,
	.ndo_set_features	= lan78xx_set_features,
	.ndo_vlan_rx_add_vid	= lan78xx_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= lan78xx_vlan_rx_kill_vid,
	.ndo_features_check	= lan78xx_features_check,
};

static void lan78xx_stat_monitor(struct timer_list *t)
{
	struct lan78xx_net *dev = timer_container_of(dev, t, stat_monitor);

	lan78xx_defer_kevent(dev, EVENT_STAT_UPDATE);
}

static int lan78xx_probe(struct usb_interface *intf,
			 const struct usb_device_id *id)
{
	struct usb_host_endpoint *ep_blkin, *ep_blkout, *ep_intr;
	struct lan78xx_net *dev;
	struct net_device *netdev;
	struct usb_device *udev;
	int ret;
	unsigned int maxp;
	unsigned int period;
	u8 *buf = NULL;

	udev = interface_to_usbdev(intf);

	netdev = alloc_etherdev(sizeof(struct lan78xx_net));
	if (!netdev) {
		dev_err(&intf->dev, "Error: OOM\n");
		return -ENOMEM;
	}

	SET_NETDEV_DEV(netdev, &intf->dev);

	dev = netdev_priv(netdev);
	dev->udev = udev;
	dev->intf = intf;
	dev->net = netdev;
	dev->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV
					| NETIF_MSG_PROBE | NETIF_MSG_LINK);

	skb_queue_head_init(&dev->rxq);
	skb_queue_head_init(&dev->txq);
	skb_queue_head_init(&dev->rxq_done);
	skb_queue_head_init(&dev->txq_pend);
	skb_queue_head_init(&dev->rxq_overflow);
	mutex_init(&dev->mdiobus_mutex);
	mutex_init(&dev->dev_mutex);

	ret = lan78xx_urb_config_init(dev);
	if (ret < 0)
		goto out2;

	ret = lan78xx_alloc_tx_resources(dev);
	if (ret < 0)
		goto out2;

	ret = lan78xx_alloc_rx_resources(dev);
	if (ret < 0)
		goto out3;

	/* MTU range: 68 - 9000 */
	netdev->max_mtu = MAX_SINGLE_PACKET_SIZE;

	netif_set_tso_max_size(netdev, LAN78XX_TSO_SIZE(dev));

	netif_napi_add(netdev, &dev->napi, lan78xx_poll);

	INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork);
	init_usb_anchor(&dev->deferred);

	netdev->netdev_ops = &lan78xx_netdev_ops;
	netdev->watchdog_timeo = TX_TIMEOUT_JIFFIES;
	netdev->ethtool_ops = &lan78xx_ethtool_ops;

	dev->delta = 1;
	timer_setup(&dev->stat_monitor, lan78xx_stat_monitor, 0);

	mutex_init(&dev->stats.access_lock);

Annotation

Implementation Notes