drivers/usb/usbip/vudc_sysfs.c

Source file repositories/reference/linux-study-clean/drivers/usb/usbip/vudc_sysfs.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/usbip/vudc_sysfs.c
Extension
.c
Size
6111 bytes
Lines
269
Domain
Driver Families
Bucket
drivers/usb
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

if (udc->connected) {
			dev_err(dev, "Device already connected");
			ret = -EBUSY;
			goto unlock;
		}

		spin_lock(&udc->ud.lock);

		if (udc->ud.status != SDEV_ST_AVAILABLE) {
			ret = -EINVAL;
			goto unlock_ud;
		}

		socket = sockfd_lookup(sockfd, &err);
		if (!socket) {
			dev_err(dev, "failed to lookup sock");
			ret = -EINVAL;
			goto unlock_ud;
		}

		if (socket->type != SOCK_STREAM) {
			dev_err(dev, "Expecting SOCK_STREAM - found %d",
				socket->type);
			ret = -EINVAL;
			goto sock_err;
		}

		/* unlock and create threads and get tasks */
		spin_unlock(&udc->ud.lock);
		spin_unlock_irqrestore(&udc->lock, flags);

		tcp_rx = kthread_create(&v_rx_loop, &udc->ud, "vudc_rx");
		if (IS_ERR(tcp_rx)) {
			sockfd_put(socket);
			mutex_unlock(&udc->ud.sysfs_lock);
			return -EINVAL;
		}
		tcp_tx = kthread_create(&v_tx_loop, &udc->ud, "vudc_tx");
		if (IS_ERR(tcp_tx)) {
			kthread_stop(tcp_rx);
			sockfd_put(socket);
			mutex_unlock(&udc->ud.sysfs_lock);
			return -EINVAL;
		}

		/* get task structs now */
		get_task_struct(tcp_rx);
		get_task_struct(tcp_tx);

		/* lock and update udc->ud state */
		spin_lock_irqsave(&udc->lock, flags);
		spin_lock(&udc->ud.lock);

		udc->ud.tcp_socket = socket;
		udc->ud.tcp_rx = tcp_rx;
		udc->ud.tcp_tx = tcp_tx;
		udc->ud.status = SDEV_ST_USED;

		spin_unlock(&udc->ud.lock);

		ktime_get_ts64(&udc->start_time);
		v_start_timer(udc);
		udc->connected = 1;

		spin_unlock_irqrestore(&udc->lock, flags);

		wake_up_process(udc->ud.tcp_rx);
		wake_up_process(udc->ud.tcp_tx);

		mutex_unlock(&udc->ud.sysfs_lock);
		return count;

	} else {
		if (!udc->connected) {
			dev_err(dev, "Device not connected");
			ret = -EINVAL;
			goto unlock;
		}

		spin_lock(&udc->ud.lock);
		if (udc->ud.status != SDEV_ST_USED) {
			ret = -EINVAL;
			goto unlock_ud;
		}
		spin_unlock(&udc->ud.lock);

		usbip_event_add(&udc->ud, VUDC_EVENT_DOWN);
	}

	spin_unlock_irqrestore(&udc->lock, flags);

Annotation

Implementation Notes