18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
48c2ecf20Sopenharmony_ci * Copyright (C) 2015-2016 Samsung Electronics
58c2ecf20Sopenharmony_ci *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
68c2ecf20Sopenharmony_ci *               Krzysztof Opasiak <k.opasiak@samsung.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/device.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/list.h>
128c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
138c2ecf20Sopenharmony_ci#include <linux/usb.h>
148c2ecf20Sopenharmony_ci#include <linux/usb/gadget.h>
158c2ecf20Sopenharmony_ci#include <linux/usb/hcd.h>
168c2ecf20Sopenharmony_ci#include <linux/kthread.h>
178c2ecf20Sopenharmony_ci#include <linux/file.h>
188c2ecf20Sopenharmony_ci#include <linux/byteorder/generic.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "usbip_common.h"
218c2ecf20Sopenharmony_ci#include "vudc.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define VIRTUAL_ENDPOINTS (1 /* ep0 */ + 15 /* in eps */ + 15 /* out eps */)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* urb-related structures alloc / free */
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic void free_urb(struct urb *urb)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	if (!urb)
318c2ecf20Sopenharmony_ci		return;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	kfree(urb->setup_packet);
348c2ecf20Sopenharmony_ci	urb->setup_packet = NULL;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	kfree(urb->transfer_buffer);
378c2ecf20Sopenharmony_ci	urb->transfer_buffer = NULL;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	usb_free_urb(urb);
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistruct urbp *alloc_urbp(void)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct urbp *urb_p;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	urb_p = kzalloc(sizeof(*urb_p), GFP_KERNEL);
478c2ecf20Sopenharmony_ci	if (!urb_p)
488c2ecf20Sopenharmony_ci		return urb_p;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	urb_p->urb = NULL;
518c2ecf20Sopenharmony_ci	urb_p->ep = NULL;
528c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&urb_p->urb_entry);
538c2ecf20Sopenharmony_ci	return urb_p;
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic void free_urbp(struct urbp *urb_p)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	kfree(urb_p);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_civoid free_urbp_and_urb(struct urbp *urb_p)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	if (!urb_p)
648c2ecf20Sopenharmony_ci		return;
658c2ecf20Sopenharmony_ci	free_urb(urb_p->urb);
668c2ecf20Sopenharmony_ci	free_urbp(urb_p);
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/* utilities ; almost verbatim from dummy_hcd.c */
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/* called with spinlock held */
738c2ecf20Sopenharmony_cistatic void nuke(struct vudc *udc, struct vep *ep)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	struct vrequest	*req;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	while (!list_empty(&ep->req_queue)) {
788c2ecf20Sopenharmony_ci		req = list_first_entry(&ep->req_queue, struct vrequest,
798c2ecf20Sopenharmony_ci				       req_entry);
808c2ecf20Sopenharmony_ci		list_del_init(&req->req_entry);
818c2ecf20Sopenharmony_ci		req->req.status = -ESHUTDOWN;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		spin_unlock(&udc->lock);
848c2ecf20Sopenharmony_ci		usb_gadget_giveback_request(&ep->ep, &req->req);
858c2ecf20Sopenharmony_ci		spin_lock(&udc->lock);
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci/* caller must hold lock */
908c2ecf20Sopenharmony_cistatic void stop_activity(struct vudc *udc)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	int i;
938c2ecf20Sopenharmony_ci	struct urbp *urb_p, *tmp;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	udc->address = 0;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	for (i = 0; i < VIRTUAL_ENDPOINTS; i++)
988c2ecf20Sopenharmony_ci		nuke(udc, &udc->ep[i]);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	list_for_each_entry_safe(urb_p, tmp, &udc->urb_queue, urb_entry) {
1018c2ecf20Sopenharmony_ci		list_del(&urb_p->urb_entry);
1028c2ecf20Sopenharmony_ci		free_urbp_and_urb(urb_p);
1038c2ecf20Sopenharmony_ci	}
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistruct vep *vudc_find_endpoint(struct vudc *udc, u8 address)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	int i;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	if ((address & ~USB_DIR_IN) == 0)
1118c2ecf20Sopenharmony_ci		return &udc->ep[0];
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	for (i = 1; i < VIRTUAL_ENDPOINTS; i++) {
1148c2ecf20Sopenharmony_ci		struct vep *ep = &udc->ep[i];
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci		if (!ep->desc)
1178c2ecf20Sopenharmony_ci			continue;
1188c2ecf20Sopenharmony_ci		if (ep->desc->bEndpointAddress == address)
1198c2ecf20Sopenharmony_ci			return ep;
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci	return NULL;
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci/* gadget ops */
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic int vgadget_get_frame(struct usb_gadget *_gadget)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct timespec64 now;
1298c2ecf20Sopenharmony_ci	struct vudc *udc = usb_gadget_to_vudc(_gadget);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	ktime_get_ts64(&now);
1328c2ecf20Sopenharmony_ci	return ((now.tv_sec - udc->start_time.tv_sec) * 1000 +
1338c2ecf20Sopenharmony_ci		(now.tv_nsec - udc->start_time.tv_nsec) / NSEC_PER_MSEC)
1348c2ecf20Sopenharmony_ci			& 0x7FF;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic int vgadget_set_selfpowered(struct usb_gadget *_gadget, int value)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	struct vudc *udc = usb_gadget_to_vudc(_gadget);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	if (value)
1428c2ecf20Sopenharmony_ci		udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
1438c2ecf20Sopenharmony_ci	else
1448c2ecf20Sopenharmony_ci		udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
1458c2ecf20Sopenharmony_ci	return 0;
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic int vgadget_pullup(struct usb_gadget *_gadget, int value)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	struct vudc *udc = usb_gadget_to_vudc(_gadget);
1518c2ecf20Sopenharmony_ci	unsigned long flags;
1528c2ecf20Sopenharmony_ci	int ret;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
1568c2ecf20Sopenharmony_ci	value = !!value;
1578c2ecf20Sopenharmony_ci	if (value == udc->pullup)
1588c2ecf20Sopenharmony_ci		goto unlock;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	udc->pullup = value;
1618c2ecf20Sopenharmony_ci	if (value) {
1628c2ecf20Sopenharmony_ci		udc->gadget.speed = min_t(u8, USB_SPEED_HIGH,
1638c2ecf20Sopenharmony_ci					   udc->driver->max_speed);
1648c2ecf20Sopenharmony_ci		udc->ep[0].ep.maxpacket = 64;
1658c2ecf20Sopenharmony_ci		/*
1668c2ecf20Sopenharmony_ci		 * This is the first place where we can ask our
1678c2ecf20Sopenharmony_ci		 * gadget driver for descriptors.
1688c2ecf20Sopenharmony_ci		 */
1698c2ecf20Sopenharmony_ci		ret = get_gadget_descs(udc);
1708c2ecf20Sopenharmony_ci		if (ret) {
1718c2ecf20Sopenharmony_ci			dev_err(&udc->gadget.dev, "Unable go get desc: %d", ret);
1728c2ecf20Sopenharmony_ci			goto unlock;
1738c2ecf20Sopenharmony_ci		}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&udc->lock, flags);
1768c2ecf20Sopenharmony_ci		usbip_start_eh(&udc->ud);
1778c2ecf20Sopenharmony_ci	} else {
1788c2ecf20Sopenharmony_ci		/* Invalidate descriptors */
1798c2ecf20Sopenharmony_ci		udc->desc_cached = 0;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&udc->lock, flags);
1828c2ecf20Sopenharmony_ci		usbip_event_add(&udc->ud, VUDC_EVENT_REMOVED);
1838c2ecf20Sopenharmony_ci		usbip_stop_eh(&udc->ud); /* Wait for eh completion */
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	return 0;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ciunlock:
1898c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
1908c2ecf20Sopenharmony_ci	return 0;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic int vgadget_udc_start(struct usb_gadget *g,
1948c2ecf20Sopenharmony_ci		struct usb_gadget_driver *driver)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct vudc *udc = usb_gadget_to_vudc(g);
1978c2ecf20Sopenharmony_ci	unsigned long flags;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
2008c2ecf20Sopenharmony_ci	udc->driver = driver;
2018c2ecf20Sopenharmony_ci	udc->pullup = udc->connected = udc->desc_cached = 0;
2028c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	return 0;
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic int vgadget_udc_stop(struct usb_gadget *g)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	struct vudc *udc = usb_gadget_to_vudc(g);
2108c2ecf20Sopenharmony_ci	unsigned long flags;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
2138c2ecf20Sopenharmony_ci	udc->driver = NULL;
2148c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
2158c2ecf20Sopenharmony_ci	return 0;
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistatic const struct usb_gadget_ops vgadget_ops = {
2198c2ecf20Sopenharmony_ci	.get_frame	= vgadget_get_frame,
2208c2ecf20Sopenharmony_ci	.set_selfpowered = vgadget_set_selfpowered,
2218c2ecf20Sopenharmony_ci	.pullup		= vgadget_pullup,
2228c2ecf20Sopenharmony_ci	.udc_start	= vgadget_udc_start,
2238c2ecf20Sopenharmony_ci	.udc_stop	= vgadget_udc_stop,
2248c2ecf20Sopenharmony_ci};
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci/* endpoint ops */
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic int vep_enable(struct usb_ep *_ep,
2308c2ecf20Sopenharmony_ci		const struct usb_endpoint_descriptor *desc)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	struct vep	*ep;
2338c2ecf20Sopenharmony_ci	struct vudc	*udc;
2348c2ecf20Sopenharmony_ci	unsigned int	maxp;
2358c2ecf20Sopenharmony_ci	unsigned long	flags;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	ep = to_vep(_ep);
2388c2ecf20Sopenharmony_ci	udc = ep_to_vudc(ep);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (!_ep || !desc || ep->desc || _ep->caps.type_control
2418c2ecf20Sopenharmony_ci			|| desc->bDescriptorType != USB_DT_ENDPOINT)
2428c2ecf20Sopenharmony_ci		return -EINVAL;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (!udc->driver)
2458c2ecf20Sopenharmony_ci		return -ESHUTDOWN;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	maxp = usb_endpoint_maxp(desc);
2508c2ecf20Sopenharmony_ci	_ep->maxpacket = maxp;
2518c2ecf20Sopenharmony_ci	ep->desc = desc;
2528c2ecf20Sopenharmony_ci	ep->type = usb_endpoint_type(desc);
2538c2ecf20Sopenharmony_ci	ep->halted = ep->wedged = 0;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	return 0;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic int vep_disable(struct usb_ep *_ep)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct vep *ep;
2638c2ecf20Sopenharmony_ci	struct vudc *udc;
2648c2ecf20Sopenharmony_ci	unsigned long flags;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	ep = to_vep(_ep);
2678c2ecf20Sopenharmony_ci	udc = ep_to_vudc(ep);
2688c2ecf20Sopenharmony_ci	if (!_ep || !ep->desc || _ep->caps.type_control)
2698c2ecf20Sopenharmony_ci		return -EINVAL;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
2728c2ecf20Sopenharmony_ci	ep->desc = NULL;
2738c2ecf20Sopenharmony_ci	nuke(udc, ep);
2748c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	return 0;
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_cistatic struct usb_request *vep_alloc_request(struct usb_ep *_ep,
2808c2ecf20Sopenharmony_ci		gfp_t mem_flags)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	struct vrequest *req;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (!_ep)
2858c2ecf20Sopenharmony_ci		return NULL;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	req = kzalloc(sizeof(*req), mem_flags);
2888c2ecf20Sopenharmony_ci	if (!req)
2898c2ecf20Sopenharmony_ci		return NULL;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&req->req_entry);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	return &req->req;
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic void vep_free_request(struct usb_ep *_ep, struct usb_request *_req)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	struct vrequest *req;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/* ep is always valid here - see usb_ep_free_request() */
3018c2ecf20Sopenharmony_ci	if (!_req)
3028c2ecf20Sopenharmony_ci		return;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	req = to_vrequest(_req);
3058c2ecf20Sopenharmony_ci	kfree(req);
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic int vep_queue(struct usb_ep *_ep, struct usb_request *_req,
3098c2ecf20Sopenharmony_ci		gfp_t mem_flags)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	struct vep *ep;
3128c2ecf20Sopenharmony_ci	struct vrequest *req;
3138c2ecf20Sopenharmony_ci	struct vudc *udc;
3148c2ecf20Sopenharmony_ci	unsigned long flags;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (!_ep || !_req)
3178c2ecf20Sopenharmony_ci		return -EINVAL;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	ep = to_vep(_ep);
3208c2ecf20Sopenharmony_ci	req = to_vrequest(_req);
3218c2ecf20Sopenharmony_ci	udc = ep_to_vudc(ep);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
3248c2ecf20Sopenharmony_ci	_req->actual = 0;
3258c2ecf20Sopenharmony_ci	_req->status = -EINPROGRESS;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	list_add_tail(&req->req_entry, &ep->req_queue);
3288c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	return 0;
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic int vep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	struct vep *ep;
3368c2ecf20Sopenharmony_ci	struct vrequest *req;
3378c2ecf20Sopenharmony_ci	struct vudc *udc;
3388c2ecf20Sopenharmony_ci	struct vrequest *lst;
3398c2ecf20Sopenharmony_ci	unsigned long flags;
3408c2ecf20Sopenharmony_ci	int ret = -EINVAL;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (!_ep || !_req)
3438c2ecf20Sopenharmony_ci		return ret;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	ep = to_vep(_ep);
3468c2ecf20Sopenharmony_ci	req = to_vrequest(_req);
3478c2ecf20Sopenharmony_ci	udc = req->udc;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	if (!udc->driver)
3508c2ecf20Sopenharmony_ci		return -ESHUTDOWN;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
3538c2ecf20Sopenharmony_ci	list_for_each_entry(lst, &ep->req_queue, req_entry) {
3548c2ecf20Sopenharmony_ci		if (&lst->req == _req) {
3558c2ecf20Sopenharmony_ci			list_del_init(&lst->req_entry);
3568c2ecf20Sopenharmony_ci			_req->status = -ECONNRESET;
3578c2ecf20Sopenharmony_ci			ret = 0;
3588c2ecf20Sopenharmony_ci			break;
3598c2ecf20Sopenharmony_ci		}
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	if (ret == 0)
3648c2ecf20Sopenharmony_ci		usb_gadget_giveback_request(_ep, _req);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	return ret;
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic int
3708c2ecf20Sopenharmony_civep_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	struct vep *ep;
3738c2ecf20Sopenharmony_ci	struct vudc *udc;
3748c2ecf20Sopenharmony_ci	unsigned long flags;
3758c2ecf20Sopenharmony_ci	int ret = 0;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	ep = to_vep(_ep);
3788c2ecf20Sopenharmony_ci	if (!_ep)
3798c2ecf20Sopenharmony_ci		return -EINVAL;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	udc = ep_to_vudc(ep);
3828c2ecf20Sopenharmony_ci	if (!udc->driver)
3838c2ecf20Sopenharmony_ci		return -ESHUTDOWN;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
3868c2ecf20Sopenharmony_ci	if (!value)
3878c2ecf20Sopenharmony_ci		ep->halted = ep->wedged = 0;
3888c2ecf20Sopenharmony_ci	else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
3898c2ecf20Sopenharmony_ci			!list_empty(&ep->req_queue))
3908c2ecf20Sopenharmony_ci		ret = -EAGAIN;
3918c2ecf20Sopenharmony_ci	else {
3928c2ecf20Sopenharmony_ci		ep->halted = 1;
3938c2ecf20Sopenharmony_ci		if (wedged)
3948c2ecf20Sopenharmony_ci			ep->wedged = 1;
3958c2ecf20Sopenharmony_ci	}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
3988c2ecf20Sopenharmony_ci	return ret;
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic int
4028c2ecf20Sopenharmony_civep_set_halt(struct usb_ep *_ep, int value)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	return vep_set_halt_and_wedge(_ep, value, 0);
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistatic int vep_set_wedge(struct usb_ep *_ep)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	return vep_set_halt_and_wedge(_ep, 1, 1);
4108c2ecf20Sopenharmony_ci}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistatic const struct usb_ep_ops vep_ops = {
4138c2ecf20Sopenharmony_ci	.enable		= vep_enable,
4148c2ecf20Sopenharmony_ci	.disable	= vep_disable,
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	.alloc_request	= vep_alloc_request,
4178c2ecf20Sopenharmony_ci	.free_request	= vep_free_request,
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	.queue		= vep_queue,
4208c2ecf20Sopenharmony_ci	.dequeue	= vep_dequeue,
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	.set_halt	= vep_set_halt,
4238c2ecf20Sopenharmony_ci	.set_wedge	= vep_set_wedge,
4248c2ecf20Sopenharmony_ci};
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci/* shutdown / reset / error handlers */
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic void vudc_shutdown(struct usbip_device *ud)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	struct vudc *udc = container_of(ud, struct vudc, ud);
4328c2ecf20Sopenharmony_ci	int call_disconnect = 0;
4338c2ecf20Sopenharmony_ci	unsigned long flags;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	dev_dbg(&udc->pdev->dev, "device shutdown");
4368c2ecf20Sopenharmony_ci	if (ud->tcp_socket)
4378c2ecf20Sopenharmony_ci		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	if (ud->tcp_rx) {
4408c2ecf20Sopenharmony_ci		kthread_stop_put(ud->tcp_rx);
4418c2ecf20Sopenharmony_ci		ud->tcp_rx = NULL;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci	if (ud->tcp_tx) {
4448c2ecf20Sopenharmony_ci		kthread_stop_put(ud->tcp_tx);
4458c2ecf20Sopenharmony_ci		ud->tcp_tx = NULL;
4468c2ecf20Sopenharmony_ci	}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	if (ud->tcp_socket) {
4498c2ecf20Sopenharmony_ci		sockfd_put(ud->tcp_socket);
4508c2ecf20Sopenharmony_ci		ud->tcp_socket = NULL;
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
4548c2ecf20Sopenharmony_ci	stop_activity(udc);
4558c2ecf20Sopenharmony_ci	if (udc->connected && udc->driver->disconnect)
4568c2ecf20Sopenharmony_ci		call_disconnect = 1;
4578c2ecf20Sopenharmony_ci	udc->connected = 0;
4588c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
4598c2ecf20Sopenharmony_ci	if (call_disconnect)
4608c2ecf20Sopenharmony_ci		udc->driver->disconnect(&udc->gadget);
4618c2ecf20Sopenharmony_ci}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_cistatic void vudc_device_reset(struct usbip_device *ud)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	struct vudc *udc = container_of(ud, struct vudc, ud);
4668c2ecf20Sopenharmony_ci	unsigned long flags;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	dev_dbg(&udc->pdev->dev, "device reset");
4698c2ecf20Sopenharmony_ci	spin_lock_irqsave(&udc->lock, flags);
4708c2ecf20Sopenharmony_ci	stop_activity(udc);
4718c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&udc->lock, flags);
4728c2ecf20Sopenharmony_ci	if (udc->driver)
4738c2ecf20Sopenharmony_ci		usb_gadget_udc_reset(&udc->gadget, udc->driver);
4748c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ud->lock, flags);
4758c2ecf20Sopenharmony_ci	ud->status = SDEV_ST_AVAILABLE;
4768c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ud->lock, flags);
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_cistatic void vudc_device_unusable(struct usbip_device *ud)
4808c2ecf20Sopenharmony_ci{
4818c2ecf20Sopenharmony_ci	unsigned long flags;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ud->lock, flags);
4848c2ecf20Sopenharmony_ci	ud->status = SDEV_ST_ERROR;
4858c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ud->lock, flags);
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci/* device setup / cleanup */
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistruct vudc_device *alloc_vudc_device(int devid)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	struct vudc_device *udc_dev = NULL;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	udc_dev = kzalloc(sizeof(*udc_dev), GFP_KERNEL);
4958c2ecf20Sopenharmony_ci	if (!udc_dev)
4968c2ecf20Sopenharmony_ci		goto out;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&udc_dev->dev_entry);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	udc_dev->pdev = platform_device_alloc(GADGET_NAME, devid);
5018c2ecf20Sopenharmony_ci	if (!udc_dev->pdev) {
5028c2ecf20Sopenharmony_ci		kfree(udc_dev);
5038c2ecf20Sopenharmony_ci		udc_dev = NULL;
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ciout:
5078c2ecf20Sopenharmony_ci	return udc_dev;
5088c2ecf20Sopenharmony_ci}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_civoid put_vudc_device(struct vudc_device *udc_dev)
5118c2ecf20Sopenharmony_ci{
5128c2ecf20Sopenharmony_ci	platform_device_put(udc_dev->pdev);
5138c2ecf20Sopenharmony_ci	kfree(udc_dev);
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic int init_vudc_hw(struct vudc *udc)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	int i;
5198c2ecf20Sopenharmony_ci	struct usbip_device *ud = &udc->ud;
5208c2ecf20Sopenharmony_ci	struct vep *ep;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	udc->ep = kcalloc(VIRTUAL_ENDPOINTS, sizeof(*udc->ep), GFP_KERNEL);
5238c2ecf20Sopenharmony_ci	if (!udc->ep)
5248c2ecf20Sopenharmony_ci		goto nomem_ep;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&udc->gadget.ep_list);
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	/* create ep0 and 15 in, 15 out general purpose eps */
5298c2ecf20Sopenharmony_ci	for (i = 0; i < VIRTUAL_ENDPOINTS; ++i) {
5308c2ecf20Sopenharmony_ci		int is_out = i % 2;
5318c2ecf20Sopenharmony_ci		int num = (i + 1) / 2;
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci		ep = &udc->ep[i];
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci		sprintf(ep->name, "ep%d%s", num,
5368c2ecf20Sopenharmony_ci			i ? (is_out ? "out" : "in") : "");
5378c2ecf20Sopenharmony_ci		ep->ep.name = ep->name;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci		ep->ep.ops = &vep_ops;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci		usb_ep_set_maxpacket_limit(&ep->ep, ~0);
5428c2ecf20Sopenharmony_ci		ep->ep.max_streams = 16;
5438c2ecf20Sopenharmony_ci		ep->gadget = &udc->gadget;
5448c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&ep->req_queue);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci		if (i == 0) {
5478c2ecf20Sopenharmony_ci			/* ep0 */
5488c2ecf20Sopenharmony_ci			ep->ep.caps.type_control = true;
5498c2ecf20Sopenharmony_ci			ep->ep.caps.dir_out = true;
5508c2ecf20Sopenharmony_ci			ep->ep.caps.dir_in = true;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci			udc->gadget.ep0 = &ep->ep;
5538c2ecf20Sopenharmony_ci		} else {
5548c2ecf20Sopenharmony_ci			/* All other eps */
5558c2ecf20Sopenharmony_ci			ep->ep.caps.type_iso = true;
5568c2ecf20Sopenharmony_ci			ep->ep.caps.type_int = true;
5578c2ecf20Sopenharmony_ci			ep->ep.caps.type_bulk = true;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci			if (is_out)
5608c2ecf20Sopenharmony_ci				ep->ep.caps.dir_out = true;
5618c2ecf20Sopenharmony_ci			else
5628c2ecf20Sopenharmony_ci				ep->ep.caps.dir_in = true;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci			list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
5658c2ecf20Sopenharmony_ci		}
5668c2ecf20Sopenharmony_ci	}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	spin_lock_init(&udc->lock);
5698c2ecf20Sopenharmony_ci	spin_lock_init(&udc->lock_tx);
5708c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&udc->urb_queue);
5718c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&udc->tx_queue);
5728c2ecf20Sopenharmony_ci	init_waitqueue_head(&udc->tx_waitq);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	spin_lock_init(&ud->lock);
5758c2ecf20Sopenharmony_ci	mutex_init(&ud->sysfs_lock);
5768c2ecf20Sopenharmony_ci	ud->status = SDEV_ST_AVAILABLE;
5778c2ecf20Sopenharmony_ci	ud->side = USBIP_VUDC;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	ud->eh_ops.shutdown = vudc_shutdown;
5808c2ecf20Sopenharmony_ci	ud->eh_ops.reset    = vudc_device_reset;
5818c2ecf20Sopenharmony_ci	ud->eh_ops.unusable = vudc_device_unusable;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	v_init_timer(udc);
5848c2ecf20Sopenharmony_ci	return 0;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cinomem_ep:
5878c2ecf20Sopenharmony_ci		return -ENOMEM;
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_cistatic void cleanup_vudc_hw(struct vudc *udc)
5918c2ecf20Sopenharmony_ci{
5928c2ecf20Sopenharmony_ci	kfree(udc->ep);
5938c2ecf20Sopenharmony_ci}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci/* platform driver ops */
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ciint vudc_probe(struct platform_device *pdev)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	struct vudc *udc;
6008c2ecf20Sopenharmony_ci	int ret = -ENOMEM;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
6038c2ecf20Sopenharmony_ci	if (!udc)
6048c2ecf20Sopenharmony_ci		goto out;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	udc->gadget.name = GADGET_NAME;
6078c2ecf20Sopenharmony_ci	udc->gadget.ops = &vgadget_ops;
6088c2ecf20Sopenharmony_ci	udc->gadget.max_speed = USB_SPEED_HIGH;
6098c2ecf20Sopenharmony_ci	udc->gadget.dev.parent = &pdev->dev;
6108c2ecf20Sopenharmony_ci	udc->pdev = pdev;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	ret = init_vudc_hw(udc);
6138c2ecf20Sopenharmony_ci	if (ret)
6148c2ecf20Sopenharmony_ci		goto err_init_vudc_hw;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
6178c2ecf20Sopenharmony_ci	if (ret < 0)
6188c2ecf20Sopenharmony_ci		goto err_add_udc;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, udc);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	return ret;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cierr_add_udc:
6258c2ecf20Sopenharmony_ci	cleanup_vudc_hw(udc);
6268c2ecf20Sopenharmony_cierr_init_vudc_hw:
6278c2ecf20Sopenharmony_ci	kfree(udc);
6288c2ecf20Sopenharmony_ciout:
6298c2ecf20Sopenharmony_ci	return ret;
6308c2ecf20Sopenharmony_ci}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ciint vudc_remove(struct platform_device *pdev)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	struct vudc *udc = platform_get_drvdata(pdev);
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	usb_del_gadget_udc(&udc->gadget);
6378c2ecf20Sopenharmony_ci	cleanup_vudc_hw(udc);
6388c2ecf20Sopenharmony_ci	kfree(udc);
6398c2ecf20Sopenharmony_ci	return 0;
6408c2ecf20Sopenharmony_ci}
641