drivers/net/usb/cx82310_eth.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/cx82310_eth.c
Extension
.c
Size
9619 bytes
Lines
376
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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

struct cx82310_priv {
	struct work_struct reenable_work;
	struct usbnet *dev;
};

/*
 * execute control command
 *  - optionally send some data (command parameters)
 *  - optionally wait for the reply
 *  - optionally read some data from the reply
 */
static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
		       u8 *wdata, int wlen, u8 *rdata, int rlen)
{
	int actual_len, retries, ret;
	struct usb_device *udev = dev->udev;
	u8 *buf = kzalloc(CMD_PACKET_SIZE, GFP_KERNEL);

	if (!buf)
		return -ENOMEM;

	/* create command packet */
	buf[0] = cmd;
	if (wdata)
		memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));

	/* send command packet */
	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
			   CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
	if (ret < 0) {
		if (cmd != CMD_GET_LINK_STATUS)
			netdev_err(dev->net, "send command %#x: error %d\n",
				   cmd, ret);
		goto end;
	}

	if (reply) {
		/* wait for reply, retry if it's empty */
		for (retries = 0; retries < CMD_REPLY_RETRY; retries++) {
			ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, CMD_EP),
					   buf, CMD_PACKET_SIZE, &actual_len,
					   CMD_TIMEOUT);
			if (ret < 0) {
				if (cmd != CMD_GET_LINK_STATUS)
					netdev_err(dev->net, "reply receive error %d\n",
						   ret);
				goto end;
			}
			if (actual_len > 0)
				break;
		}
		if (actual_len == 0) {
			netdev_err(dev->net, "no reply to command %#x\n", cmd);
			ret = -EIO;
			goto end;
		}
		if (buf[0] != cmd) {
			netdev_err(dev->net, "got reply to command %#x, expected: %#x\n",
				   buf[0], cmd);
			ret = -EIO;
			goto end;
		}
		if (buf[1] != STATUS_SUCCESS) {
			netdev_err(dev->net, "command %#x failed: %#x\n", cmd,
				   buf[1]);
			ret = -EIO;
			goto end;
		}
		if (rdata)
			memcpy(rdata, buf + 4,
			       min_t(int, rlen, CMD_PACKET_SIZE - 4));
	}
end:
	kfree(buf);
	return ret;
}

static int cx82310_enable_ethernet(struct usbnet *dev)
{
	int ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);

	if (ret)
		netdev_err(dev->net, "unable to enable ethernet mode: %d\n",
			   ret);
	return ret;
}

static void cx82310_reenable_work(struct work_struct *work)
{
	struct cx82310_priv *priv = container_of(work, struct cx82310_priv,

Annotation

Implementation Notes