18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2003-2008 Takahiro Hirofuchi
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/kthread.h>
78c2ecf20Sopenharmony_ci#include <linux/socket.h>
88c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "usbip_common.h"
118c2ecf20Sopenharmony_ci#include "stub.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */
148c2ecf20Sopenharmony_civoid stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum,
158c2ecf20Sopenharmony_ci			     __u32 status)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	struct stub_unlink *unlink;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC);
208c2ecf20Sopenharmony_ci	if (!unlink) {
218c2ecf20Sopenharmony_ci		usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC);
228c2ecf20Sopenharmony_ci		return;
238c2ecf20Sopenharmony_ci	}
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	unlink->seqnum = seqnum;
268c2ecf20Sopenharmony_ci	unlink->status = status;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	list_add_tail(&unlink->list, &sdev->unlink_tx);
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/**
328c2ecf20Sopenharmony_ci * stub_complete - completion handler of a usbip urb
338c2ecf20Sopenharmony_ci * @urb: pointer to the urb completed
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * When a urb has completed, the USB core driver calls this function mostly in
368c2ecf20Sopenharmony_ci * the interrupt context. To return the result of a urb, the completed urb is
378c2ecf20Sopenharmony_ci * linked to the pending list of returning.
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_civoid stub_complete(struct urb *urb)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	struct stub_priv *priv = (struct stub_priv *) urb->context;
438c2ecf20Sopenharmony_ci	struct stub_device *sdev = priv->sdev;
448c2ecf20Sopenharmony_ci	unsigned long flags;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	usbip_dbg_stub_tx("complete! status %d\n", urb->status);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	switch (urb->status) {
498c2ecf20Sopenharmony_ci	case 0:
508c2ecf20Sopenharmony_ci		/* OK */
518c2ecf20Sopenharmony_ci		break;
528c2ecf20Sopenharmony_ci	case -ENOENT:
538c2ecf20Sopenharmony_ci		dev_info(&urb->dev->dev,
548c2ecf20Sopenharmony_ci			 "stopped by a call to usb_kill_urb() because of cleaning up a virtual connection\n");
558c2ecf20Sopenharmony_ci		return;
568c2ecf20Sopenharmony_ci	case -ECONNRESET:
578c2ecf20Sopenharmony_ci		dev_info(&urb->dev->dev,
588c2ecf20Sopenharmony_ci			 "unlinked by a call to usb_unlink_urb()\n");
598c2ecf20Sopenharmony_ci		break;
608c2ecf20Sopenharmony_ci	case -EPIPE:
618c2ecf20Sopenharmony_ci		dev_info(&urb->dev->dev, "endpoint %d is stalled\n",
628c2ecf20Sopenharmony_ci			 usb_pipeendpoint(urb->pipe));
638c2ecf20Sopenharmony_ci		break;
648c2ecf20Sopenharmony_ci	case -ESHUTDOWN:
658c2ecf20Sopenharmony_ci		dev_info(&urb->dev->dev, "device removed?\n");
668c2ecf20Sopenharmony_ci		break;
678c2ecf20Sopenharmony_ci	default:
688c2ecf20Sopenharmony_ci		dev_info(&urb->dev->dev,
698c2ecf20Sopenharmony_ci			 "urb completion with non-zero status %d\n",
708c2ecf20Sopenharmony_ci			 urb->status);
718c2ecf20Sopenharmony_ci		break;
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/*
758c2ecf20Sopenharmony_ci	 * If the server breaks single SG request into the several URBs, the
768c2ecf20Sopenharmony_ci	 * URBs must be reassembled before sending completed URB to the vhci.
778c2ecf20Sopenharmony_ci	 * Don't wake up the tx thread until all the URBs are completed.
788c2ecf20Sopenharmony_ci	 */
798c2ecf20Sopenharmony_ci	if (priv->sgl) {
808c2ecf20Sopenharmony_ci		priv->completed_urbs++;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci		/* Only save the first error status */
838c2ecf20Sopenharmony_ci		if (urb->status && !priv->urb_status)
848c2ecf20Sopenharmony_ci			priv->urb_status = urb->status;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci		if (priv->completed_urbs < priv->num_urbs)
878c2ecf20Sopenharmony_ci			return;
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	/* link a urb to the queue of tx. */
918c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sdev->priv_lock, flags);
928c2ecf20Sopenharmony_ci	if (sdev->ud.tcp_socket == NULL) {
938c2ecf20Sopenharmony_ci		usbip_dbg_stub_tx("ignore urb for closed connection\n");
948c2ecf20Sopenharmony_ci		/* It will be freed in stub_device_cleanup_urbs(). */
958c2ecf20Sopenharmony_ci	} else if (priv->unlinking) {
968c2ecf20Sopenharmony_ci		stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status);
978c2ecf20Sopenharmony_ci		stub_free_priv_and_urb(priv);
988c2ecf20Sopenharmony_ci	} else {
998c2ecf20Sopenharmony_ci		list_move_tail(&priv->list, &sdev->priv_tx);
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sdev->priv_lock, flags);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	/* wake up tx_thread */
1048c2ecf20Sopenharmony_ci	wake_up(&sdev->tx_waitq);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic inline void setup_base_pdu(struct usbip_header_basic *base,
1088c2ecf20Sopenharmony_ci				  __u32 command, __u32 seqnum)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	base->command	= command;
1118c2ecf20Sopenharmony_ci	base->seqnum	= seqnum;
1128c2ecf20Sopenharmony_ci	base->devid	= 0;
1138c2ecf20Sopenharmony_ci	base->ep	= 0;
1148c2ecf20Sopenharmony_ci	base->direction = 0;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	struct stub_priv *priv = (struct stub_priv *) urb->context;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum);
1228c2ecf20Sopenharmony_ci	usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1);
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic void setup_ret_unlink_pdu(struct usbip_header *rpdu,
1268c2ecf20Sopenharmony_ci				 struct stub_unlink *unlink)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum);
1298c2ecf20Sopenharmony_ci	rpdu->u.ret_unlink.status = unlink->status;
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	unsigned long flags;
1358c2ecf20Sopenharmony_ci	struct stub_priv *priv, *tmp;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sdev->priv_lock, flags);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) {
1408c2ecf20Sopenharmony_ci		list_move_tail(&priv->list, &sdev->priv_free);
1418c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sdev->priv_lock, flags);
1428c2ecf20Sopenharmony_ci		return priv;
1438c2ecf20Sopenharmony_ci	}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sdev->priv_lock, flags);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	return NULL;
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic int stub_send_ret_submit(struct stub_device *sdev)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	unsigned long flags;
1538c2ecf20Sopenharmony_ci	struct stub_priv *priv, *tmp;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	struct msghdr msg;
1568c2ecf20Sopenharmony_ci	size_t txsize;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	size_t total_size = 0;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	while ((priv = dequeue_from_priv_tx(sdev)) != NULL) {
1618c2ecf20Sopenharmony_ci		struct urb *urb = priv->urbs[0];
1628c2ecf20Sopenharmony_ci		struct usbip_header pdu_header;
1638c2ecf20Sopenharmony_ci		struct usbip_iso_packet_descriptor *iso_buffer = NULL;
1648c2ecf20Sopenharmony_ci		struct kvec *iov = NULL;
1658c2ecf20Sopenharmony_ci		struct scatterlist *sg;
1668c2ecf20Sopenharmony_ci		u32 actual_length = 0;
1678c2ecf20Sopenharmony_ci		int iovnum = 0;
1688c2ecf20Sopenharmony_ci		int ret;
1698c2ecf20Sopenharmony_ci		int i;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci		txsize = 0;
1728c2ecf20Sopenharmony_ci		memset(&pdu_header, 0, sizeof(pdu_header));
1738c2ecf20Sopenharmony_ci		memset(&msg, 0, sizeof(msg));
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		if (urb->actual_length > 0 && !urb->transfer_buffer &&
1768c2ecf20Sopenharmony_ci		   !urb->num_sgs) {
1778c2ecf20Sopenharmony_ci			dev_err(&sdev->udev->dev,
1788c2ecf20Sopenharmony_ci				"urb: actual_length %d transfer_buffer null\n",
1798c2ecf20Sopenharmony_ci				urb->actual_length);
1808c2ecf20Sopenharmony_ci			return -1;
1818c2ecf20Sopenharmony_ci		}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci		if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
1848c2ecf20Sopenharmony_ci			iovnum = 2 + urb->number_of_packets;
1858c2ecf20Sopenharmony_ci		else if (usb_pipein(urb->pipe) && urb->actual_length > 0 &&
1868c2ecf20Sopenharmony_ci			urb->num_sgs)
1878c2ecf20Sopenharmony_ci			iovnum = 1 + urb->num_sgs;
1888c2ecf20Sopenharmony_ci		else if (usb_pipein(urb->pipe) && priv->sgl)
1898c2ecf20Sopenharmony_ci			iovnum = 1 + priv->num_urbs;
1908c2ecf20Sopenharmony_ci		else
1918c2ecf20Sopenharmony_ci			iovnum = 2;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci		iov = kcalloc(iovnum, sizeof(struct kvec), GFP_KERNEL);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		if (!iov) {
1968c2ecf20Sopenharmony_ci			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC);
1978c2ecf20Sopenharmony_ci			return -1;
1988c2ecf20Sopenharmony_ci		}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		iovnum = 0;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci		/* 1. setup usbip_header */
2038c2ecf20Sopenharmony_ci		setup_ret_submit_pdu(&pdu_header, urb);
2048c2ecf20Sopenharmony_ci		usbip_dbg_stub_tx("setup txdata seqnum: %d\n",
2058c2ecf20Sopenharmony_ci				  pdu_header.base.seqnum);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci		if (priv->sgl) {
2088c2ecf20Sopenharmony_ci			for (i = 0; i < priv->num_urbs; i++)
2098c2ecf20Sopenharmony_ci				actual_length += priv->urbs[i]->actual_length;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci			pdu_header.u.ret_submit.status = priv->urb_status;
2128c2ecf20Sopenharmony_ci			pdu_header.u.ret_submit.actual_length = actual_length;
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci		usbip_header_correct_endian(&pdu_header, 1);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		iov[iovnum].iov_base = &pdu_header;
2188c2ecf20Sopenharmony_ci		iov[iovnum].iov_len  = sizeof(pdu_header);
2198c2ecf20Sopenharmony_ci		iovnum++;
2208c2ecf20Sopenharmony_ci		txsize += sizeof(pdu_header);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		/* 2. setup transfer buffer */
2238c2ecf20Sopenharmony_ci		if (usb_pipein(urb->pipe) && priv->sgl) {
2248c2ecf20Sopenharmony_ci			/* If the server split a single SG request into several
2258c2ecf20Sopenharmony_ci			 * URBs because the server's HCD doesn't support SG,
2268c2ecf20Sopenharmony_ci			 * reassemble the split URB buffers into a single
2278c2ecf20Sopenharmony_ci			 * return command.
2288c2ecf20Sopenharmony_ci			 */
2298c2ecf20Sopenharmony_ci			for (i = 0; i < priv->num_urbs; i++) {
2308c2ecf20Sopenharmony_ci				iov[iovnum].iov_base =
2318c2ecf20Sopenharmony_ci					priv->urbs[i]->transfer_buffer;
2328c2ecf20Sopenharmony_ci				iov[iovnum].iov_len =
2338c2ecf20Sopenharmony_ci					priv->urbs[i]->actual_length;
2348c2ecf20Sopenharmony_ci				iovnum++;
2358c2ecf20Sopenharmony_ci			}
2368c2ecf20Sopenharmony_ci			txsize += actual_length;
2378c2ecf20Sopenharmony_ci		} else if (usb_pipein(urb->pipe) &&
2388c2ecf20Sopenharmony_ci		    usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
2398c2ecf20Sopenharmony_ci		    urb->actual_length > 0) {
2408c2ecf20Sopenharmony_ci			if (urb->num_sgs) {
2418c2ecf20Sopenharmony_ci				unsigned int copy = urb->actual_length;
2428c2ecf20Sopenharmony_ci				int size;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci				for_each_sg(urb->sg, sg, urb->num_sgs, i) {
2458c2ecf20Sopenharmony_ci					if (copy == 0)
2468c2ecf20Sopenharmony_ci						break;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci					if (copy < sg->length)
2498c2ecf20Sopenharmony_ci						size = copy;
2508c2ecf20Sopenharmony_ci					else
2518c2ecf20Sopenharmony_ci						size = sg->length;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci					iov[iovnum].iov_base = sg_virt(sg);
2548c2ecf20Sopenharmony_ci					iov[iovnum].iov_len = size;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci					iovnum++;
2578c2ecf20Sopenharmony_ci					copy -= size;
2588c2ecf20Sopenharmony_ci				}
2598c2ecf20Sopenharmony_ci			} else {
2608c2ecf20Sopenharmony_ci				iov[iovnum].iov_base = urb->transfer_buffer;
2618c2ecf20Sopenharmony_ci				iov[iovnum].iov_len  = urb->actual_length;
2628c2ecf20Sopenharmony_ci				iovnum++;
2638c2ecf20Sopenharmony_ci			}
2648c2ecf20Sopenharmony_ci			txsize += urb->actual_length;
2658c2ecf20Sopenharmony_ci		} else if (usb_pipein(urb->pipe) &&
2668c2ecf20Sopenharmony_ci			   usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
2678c2ecf20Sopenharmony_ci			/*
2688c2ecf20Sopenharmony_ci			 * For isochronous packets: actual length is the sum of
2698c2ecf20Sopenharmony_ci			 * the actual length of the individual, packets, but as
2708c2ecf20Sopenharmony_ci			 * the packet offsets are not changed there will be
2718c2ecf20Sopenharmony_ci			 * padding between the packets. To optimally use the
2728c2ecf20Sopenharmony_ci			 * bandwidth the padding is not transmitted.
2738c2ecf20Sopenharmony_ci			 */
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci			int i;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci			for (i = 0; i < urb->number_of_packets; i++) {
2788c2ecf20Sopenharmony_ci				iov[iovnum].iov_base = urb->transfer_buffer +
2798c2ecf20Sopenharmony_ci					urb->iso_frame_desc[i].offset;
2808c2ecf20Sopenharmony_ci				iov[iovnum].iov_len =
2818c2ecf20Sopenharmony_ci					urb->iso_frame_desc[i].actual_length;
2828c2ecf20Sopenharmony_ci				iovnum++;
2838c2ecf20Sopenharmony_ci				txsize += urb->iso_frame_desc[i].actual_length;
2848c2ecf20Sopenharmony_ci			}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci			if (txsize != sizeof(pdu_header) + urb->actual_length) {
2878c2ecf20Sopenharmony_ci				dev_err(&sdev->udev->dev,
2888c2ecf20Sopenharmony_ci					"actual length of urb %d does not match iso packet sizes %zu\n",
2898c2ecf20Sopenharmony_ci					urb->actual_length,
2908c2ecf20Sopenharmony_ci					txsize-sizeof(pdu_header));
2918c2ecf20Sopenharmony_ci				kfree(iov);
2928c2ecf20Sopenharmony_ci				usbip_event_add(&sdev->ud,
2938c2ecf20Sopenharmony_ci						SDEV_EVENT_ERROR_TCP);
2948c2ecf20Sopenharmony_ci				return -1;
2958c2ecf20Sopenharmony_ci			}
2968c2ecf20Sopenharmony_ci		}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci		/* 3. setup iso_packet_descriptor */
2998c2ecf20Sopenharmony_ci		if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
3008c2ecf20Sopenharmony_ci			ssize_t len = 0;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci			iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
3038c2ecf20Sopenharmony_ci			if (!iso_buffer) {
3048c2ecf20Sopenharmony_ci				usbip_event_add(&sdev->ud,
3058c2ecf20Sopenharmony_ci						SDEV_EVENT_ERROR_MALLOC);
3068c2ecf20Sopenharmony_ci				kfree(iov);
3078c2ecf20Sopenharmony_ci				return -1;
3088c2ecf20Sopenharmony_ci			}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci			iov[iovnum].iov_base = iso_buffer;
3118c2ecf20Sopenharmony_ci			iov[iovnum].iov_len  = len;
3128c2ecf20Sopenharmony_ci			txsize += len;
3138c2ecf20Sopenharmony_ci			iovnum++;
3148c2ecf20Sopenharmony_ci		}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci		ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg,
3178c2ecf20Sopenharmony_ci						iov,  iovnum, txsize);
3188c2ecf20Sopenharmony_ci		if (ret != txsize) {
3198c2ecf20Sopenharmony_ci			dev_err(&sdev->udev->dev,
3208c2ecf20Sopenharmony_ci				"sendmsg failed!, retval %d for %zd\n",
3218c2ecf20Sopenharmony_ci				ret, txsize);
3228c2ecf20Sopenharmony_ci			kfree(iov);
3238c2ecf20Sopenharmony_ci			kfree(iso_buffer);
3248c2ecf20Sopenharmony_ci			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
3258c2ecf20Sopenharmony_ci			return -1;
3268c2ecf20Sopenharmony_ci		}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci		kfree(iov);
3298c2ecf20Sopenharmony_ci		kfree(iso_buffer);
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci		total_size += txsize;
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sdev->priv_lock, flags);
3358c2ecf20Sopenharmony_ci	list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
3368c2ecf20Sopenharmony_ci		stub_free_priv_and_urb(priv);
3378c2ecf20Sopenharmony_ci	}
3388c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sdev->priv_lock, flags);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	return total_size;
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	unsigned long flags;
3468c2ecf20Sopenharmony_ci	struct stub_unlink *unlink, *tmp;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sdev->priv_lock, flags);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
3518c2ecf20Sopenharmony_ci		list_move_tail(&unlink->list, &sdev->unlink_free);
3528c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sdev->priv_lock, flags);
3538c2ecf20Sopenharmony_ci		return unlink;
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sdev->priv_lock, flags);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	return NULL;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic int stub_send_ret_unlink(struct stub_device *sdev)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	unsigned long flags;
3648c2ecf20Sopenharmony_ci	struct stub_unlink *unlink, *tmp;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	struct msghdr msg;
3678c2ecf20Sopenharmony_ci	struct kvec iov[1];
3688c2ecf20Sopenharmony_ci	size_t txsize;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	size_t total_size = 0;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) {
3738c2ecf20Sopenharmony_ci		int ret;
3748c2ecf20Sopenharmony_ci		struct usbip_header pdu_header;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci		txsize = 0;
3778c2ecf20Sopenharmony_ci		memset(&pdu_header, 0, sizeof(pdu_header));
3788c2ecf20Sopenharmony_ci		memset(&msg, 0, sizeof(msg));
3798c2ecf20Sopenharmony_ci		memset(&iov, 0, sizeof(iov));
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		usbip_dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		/* 1. setup usbip_header */
3848c2ecf20Sopenharmony_ci		setup_ret_unlink_pdu(&pdu_header, unlink);
3858c2ecf20Sopenharmony_ci		usbip_header_correct_endian(&pdu_header, 1);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		iov[0].iov_base = &pdu_header;
3888c2ecf20Sopenharmony_ci		iov[0].iov_len  = sizeof(pdu_header);
3898c2ecf20Sopenharmony_ci		txsize += sizeof(pdu_header);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci		ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
3928c2ecf20Sopenharmony_ci				     1, txsize);
3938c2ecf20Sopenharmony_ci		if (ret != txsize) {
3948c2ecf20Sopenharmony_ci			dev_err(&sdev->udev->dev,
3958c2ecf20Sopenharmony_ci				"sendmsg failed!, retval %d for %zd\n",
3968c2ecf20Sopenharmony_ci				ret, txsize);
3978c2ecf20Sopenharmony_ci			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
3988c2ecf20Sopenharmony_ci			return -1;
3998c2ecf20Sopenharmony_ci		}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		usbip_dbg_stub_tx("send txdata\n");
4028c2ecf20Sopenharmony_ci		total_size += txsize;
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sdev->priv_lock, flags);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) {
4088c2ecf20Sopenharmony_ci		list_del(&unlink->list);
4098c2ecf20Sopenharmony_ci		kfree(unlink);
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sdev->priv_lock, flags);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	return total_size;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ciint stub_tx_loop(void *data)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	struct usbip_device *ud = data;
4208c2ecf20Sopenharmony_ci	struct stub_device *sdev = container_of(ud, struct stub_device, ud);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	while (!kthread_should_stop()) {
4238c2ecf20Sopenharmony_ci		if (usbip_event_happened(ud))
4248c2ecf20Sopenharmony_ci			break;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci		/*
4278c2ecf20Sopenharmony_ci		 * send_ret_submit comes earlier than send_ret_unlink.  stub_rx
4288c2ecf20Sopenharmony_ci		 * looks at only priv_init queue. If the completion of a URB is
4298c2ecf20Sopenharmony_ci		 * earlier than the receive of CMD_UNLINK, priv is moved to
4308c2ecf20Sopenharmony_ci		 * priv_tx queue and stub_rx does not find the target priv. In
4318c2ecf20Sopenharmony_ci		 * this case, vhci_rx receives the result of the submit request
4328c2ecf20Sopenharmony_ci		 * and then receives the result of the unlink request. The
4338c2ecf20Sopenharmony_ci		 * result of the submit is given back to the usbcore as the
4348c2ecf20Sopenharmony_ci		 * completion of the unlink request. The request of the
4358c2ecf20Sopenharmony_ci		 * unlink is ignored. This is ok because a driver who calls
4368c2ecf20Sopenharmony_ci		 * usb_unlink_urb() understands the unlink was too late by
4378c2ecf20Sopenharmony_ci		 * getting the status of the given-backed URB which has the
4388c2ecf20Sopenharmony_ci		 * status of usb_submit_urb().
4398c2ecf20Sopenharmony_ci		 */
4408c2ecf20Sopenharmony_ci		if (stub_send_ret_submit(sdev) < 0)
4418c2ecf20Sopenharmony_ci			break;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci		if (stub_send_ret_unlink(sdev) < 0)
4448c2ecf20Sopenharmony_ci			break;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci		wait_event_interruptible(sdev->tx_waitq,
4478c2ecf20Sopenharmony_ci					 (!list_empty(&sdev->priv_tx) ||
4488c2ecf20Sopenharmony_ci					  !list_empty(&sdev->unlink_tx) ||
4498c2ecf20Sopenharmony_ci					  kthread_should_stop()));
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	return 0;
4538c2ecf20Sopenharmony_ci}
454