drivers/net/mctp/mctp-i2c.c

Source file repositories/reference/linux-study-clean/drivers/net/mctp/mctp-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/net/mctp/mctp-i2c.c
Extension
.c
Size
29155 bytes
Lines
1157
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 mctp_i2c_ops = {
	.ndo_start_xmit = mctp_i2c_start_xmit,
	.ndo_uninit = mctp_i2c_ndo_uninit,
	.ndo_open = mctp_i2c_ndo_open,
};

static const struct header_ops mctp_i2c_headops = {
	.create = mctp_i2c_header_create,
};

static const struct mctp_netdev_ops mctp_i2c_mctp_ops = {
	.release_flow = mctp_i2c_release_flow,
};

static void mctp_i2c_net_setup(struct net_device *dev)
{
	dev->type = ARPHRD_MCTP;

	dev->mtu = MCTP_I2C_MAXMTU;
	dev->min_mtu = MCTP_I2C_MINMTU;
	dev->max_mtu = MCTP_I2C_MAXMTU;
	dev->tx_queue_len = MCTP_I2C_TX_QUEUE_LEN;

	dev->hard_header_len = sizeof(struct mctp_i2c_hdr);
	dev->addr_len = 1;

	dev->netdev_ops		= &mctp_i2c_ops;
	dev->header_ops		= &mctp_i2c_headops;
}

/* Populates the mctp_i2c_dev priv struct for a netdev.
 * Returns an error pointer on failure.
 */
static struct mctp_i2c_dev *mctp_i2c_midev_init(struct net_device *dev,
						struct mctp_i2c_client *mcli,
						struct i2c_adapter *adap)
{
	struct mctp_i2c_dev *midev = netdev_priv(dev);
	unsigned long flags;

	midev->tx_thread = kthread_create(mctp_i2c_tx_thread, midev,
					  "%s/tx", dev->name);
	if (IS_ERR(midev->tx_thread))
		return ERR_CAST(midev->tx_thread);

	midev->ndev = dev;
	get_device(&adap->dev);
	midev->adapter = adap;
	get_device(&mcli->client->dev);
	midev->client = mcli;
	INIT_LIST_HEAD(&midev->list);
	spin_lock_init(&midev->lock);
	midev->i2c_lock_count = 0;
	midev->release_count = 0;
	init_completion(&midev->rx_done);
	complete(&midev->rx_done);
	init_waitqueue_head(&midev->tx_wq);
	skb_queue_head_init(&midev->tx_queue);

	/* Add to the parent mcli */
	spin_lock_irqsave(&mcli->sel_lock, flags);
	list_add(&midev->list, &mcli->devs);
	/* Select a device by default */
	if (!mcli->sel)
		__mctp_i2c_device_select(mcli, midev);
	spin_unlock_irqrestore(&mcli->sel_lock, flags);

	/* Start the worker thread */
	wake_up_process(midev->tx_thread);

	return midev;
}

/* Counterpart of mctp_i2c_midev_init */
static void mctp_i2c_midev_free(struct mctp_i2c_dev *midev)
{
	struct mctp_i2c_client *mcli = midev->client;
	unsigned long flags;

	if (midev->tx_thread) {
		kthread_stop(midev->tx_thread);
		midev->tx_thread = NULL;
	}

	/* Unconditionally unlock on close */
	mctp_i2c_unlock_reset(midev);

	/* Remove the netdev from the parent i2c client. */
	spin_lock_irqsave(&mcli->sel_lock, flags);
	list_del(&midev->list);

Annotation

Implementation Notes