xref: /OK3568_Linux_fs/kernel/drivers/usb/usbip/vhci_tx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2003-2008 Takahiro Hirofuchi
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/kthread.h>
7*4882a593Smuzhiyun #include <linux/slab.h>
8*4882a593Smuzhiyun #include <linux/scatterlist.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "usbip_common.h"
11*4882a593Smuzhiyun #include "vhci.h"
12*4882a593Smuzhiyun 
setup_cmd_submit_pdu(struct usbip_header * pdup,struct urb * urb)13*4882a593Smuzhiyun static void setup_cmd_submit_pdu(struct usbip_header *pdup,  struct urb *urb)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv);
16*4882a593Smuzhiyun 	struct vhci_device *vdev = priv->vdev;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	usbip_dbg_vhci_tx("URB, local devnum %u, remote devid %u\n",
19*4882a593Smuzhiyun 			  usb_pipedevice(urb->pipe), vdev->devid);
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 	pdup->base.command   = USBIP_CMD_SUBMIT;
22*4882a593Smuzhiyun 	pdup->base.seqnum    = priv->seqnum;
23*4882a593Smuzhiyun 	pdup->base.devid     = vdev->devid;
24*4882a593Smuzhiyun 	pdup->base.direction = usb_pipein(urb->pipe) ?
25*4882a593Smuzhiyun 		USBIP_DIR_IN : USBIP_DIR_OUT;
26*4882a593Smuzhiyun 	pdup->base.ep	     = usb_pipeendpoint(urb->pipe);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if (urb->setup_packet)
31*4882a593Smuzhiyun 		memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
dequeue_from_priv_tx(struct vhci_device * vdev)34*4882a593Smuzhiyun static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	struct vhci_priv *priv, *tmp;
37*4882a593Smuzhiyun 	unsigned long flags;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	spin_lock_irqsave(&vdev->priv_lock, flags);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
42*4882a593Smuzhiyun 		list_move_tail(&priv->list, &vdev->priv_rx);
43*4882a593Smuzhiyun 		spin_unlock_irqrestore(&vdev->priv_lock, flags);
44*4882a593Smuzhiyun 		return priv;
45*4882a593Smuzhiyun 	}
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	spin_unlock_irqrestore(&vdev->priv_lock, flags);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	return NULL;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
vhci_send_cmd_submit(struct vhci_device * vdev)52*4882a593Smuzhiyun static int vhci_send_cmd_submit(struct vhci_device *vdev)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	struct usbip_iso_packet_descriptor *iso_buffer = NULL;
55*4882a593Smuzhiyun 	struct vhci_priv *priv = NULL;
56*4882a593Smuzhiyun 	struct scatterlist *sg;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	struct msghdr msg;
59*4882a593Smuzhiyun 	struct kvec *iov;
60*4882a593Smuzhiyun 	size_t txsize;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	size_t total_size = 0;
63*4882a593Smuzhiyun 	int iovnum;
64*4882a593Smuzhiyun 	int err = -ENOMEM;
65*4882a593Smuzhiyun 	int i;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	while ((priv = dequeue_from_priv_tx(vdev)) != NULL) {
68*4882a593Smuzhiyun 		int ret;
69*4882a593Smuzhiyun 		struct urb *urb = priv->urb;
70*4882a593Smuzhiyun 		struct usbip_header pdu_header;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 		txsize = 0;
73*4882a593Smuzhiyun 		memset(&pdu_header, 0, sizeof(pdu_header));
74*4882a593Smuzhiyun 		memset(&msg, 0, sizeof(msg));
75*4882a593Smuzhiyun 		memset(&iov, 0, sizeof(iov));
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 		usbip_dbg_vhci_tx("setup txdata urb seqnum %lu\n",
78*4882a593Smuzhiyun 				  priv->seqnum);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 		if (urb->num_sgs && usb_pipeout(urb->pipe))
81*4882a593Smuzhiyun 			iovnum = 2 + urb->num_sgs;
82*4882a593Smuzhiyun 		else
83*4882a593Smuzhiyun 			iovnum = 3;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 		iov = kcalloc(iovnum, sizeof(*iov), GFP_KERNEL);
86*4882a593Smuzhiyun 		if (!iov) {
87*4882a593Smuzhiyun 			usbip_event_add(&vdev->ud, SDEV_EVENT_ERROR_MALLOC);
88*4882a593Smuzhiyun 			return -ENOMEM;
89*4882a593Smuzhiyun 		}
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 		if (urb->num_sgs)
92*4882a593Smuzhiyun 			urb->transfer_flags |= URB_DMA_MAP_SG;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 		/* 1. setup usbip_header */
95*4882a593Smuzhiyun 		setup_cmd_submit_pdu(&pdu_header, urb);
96*4882a593Smuzhiyun 		usbip_header_correct_endian(&pdu_header, 1);
97*4882a593Smuzhiyun 		iovnum = 0;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 		iov[iovnum].iov_base = &pdu_header;
100*4882a593Smuzhiyun 		iov[iovnum].iov_len  = sizeof(pdu_header);
101*4882a593Smuzhiyun 		txsize += sizeof(pdu_header);
102*4882a593Smuzhiyun 		iovnum++;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 		/* 2. setup transfer buffer */
105*4882a593Smuzhiyun 		if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) {
106*4882a593Smuzhiyun 			if (urb->num_sgs &&
107*4882a593Smuzhiyun 				      !usb_endpoint_xfer_isoc(&urb->ep->desc)) {
108*4882a593Smuzhiyun 				for_each_sg(urb->sg, sg, urb->num_sgs, i) {
109*4882a593Smuzhiyun 					iov[iovnum].iov_base = sg_virt(sg);
110*4882a593Smuzhiyun 					iov[iovnum].iov_len = sg->length;
111*4882a593Smuzhiyun 					iovnum++;
112*4882a593Smuzhiyun 				}
113*4882a593Smuzhiyun 			} else {
114*4882a593Smuzhiyun 				iov[iovnum].iov_base = urb->transfer_buffer;
115*4882a593Smuzhiyun 				iov[iovnum].iov_len  =
116*4882a593Smuzhiyun 						urb->transfer_buffer_length;
117*4882a593Smuzhiyun 				iovnum++;
118*4882a593Smuzhiyun 			}
119*4882a593Smuzhiyun 			txsize += urb->transfer_buffer_length;
120*4882a593Smuzhiyun 		}
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 		/* 3. setup iso_packet_descriptor */
123*4882a593Smuzhiyun 		if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
124*4882a593Smuzhiyun 			ssize_t len = 0;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 			iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
127*4882a593Smuzhiyun 			if (!iso_buffer) {
128*4882a593Smuzhiyun 				usbip_event_add(&vdev->ud,
129*4882a593Smuzhiyun 						SDEV_EVENT_ERROR_MALLOC);
130*4882a593Smuzhiyun 				goto err_iso_buffer;
131*4882a593Smuzhiyun 			}
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 			iov[iovnum].iov_base = iso_buffer;
134*4882a593Smuzhiyun 			iov[iovnum].iov_len  = len;
135*4882a593Smuzhiyun 			iovnum++;
136*4882a593Smuzhiyun 			txsize += len;
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 		ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, iovnum,
140*4882a593Smuzhiyun 				     txsize);
141*4882a593Smuzhiyun 		if (ret != txsize) {
142*4882a593Smuzhiyun 			pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
143*4882a593Smuzhiyun 			       txsize);
144*4882a593Smuzhiyun 			usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
145*4882a593Smuzhiyun 			err = -EPIPE;
146*4882a593Smuzhiyun 			goto err_tx;
147*4882a593Smuzhiyun 		}
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 		kfree(iov);
150*4882a593Smuzhiyun 		/* This is only for isochronous case */
151*4882a593Smuzhiyun 		kfree(iso_buffer);
152*4882a593Smuzhiyun 		iso_buffer = NULL;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 		usbip_dbg_vhci_tx("send txdata\n");
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 		total_size += txsize;
157*4882a593Smuzhiyun 	}
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	return total_size;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun err_tx:
162*4882a593Smuzhiyun 	kfree(iso_buffer);
163*4882a593Smuzhiyun err_iso_buffer:
164*4882a593Smuzhiyun 	kfree(iov);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return err;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
dequeue_from_unlink_tx(struct vhci_device * vdev)169*4882a593Smuzhiyun static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct vhci_unlink *unlink, *tmp;
172*4882a593Smuzhiyun 	unsigned long flags;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	spin_lock_irqsave(&vdev->priv_lock, flags);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
177*4882a593Smuzhiyun 		list_move_tail(&unlink->list, &vdev->unlink_rx);
178*4882a593Smuzhiyun 		spin_unlock_irqrestore(&vdev->priv_lock, flags);
179*4882a593Smuzhiyun 		return unlink;
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	spin_unlock_irqrestore(&vdev->priv_lock, flags);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	return NULL;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
vhci_send_cmd_unlink(struct vhci_device * vdev)187*4882a593Smuzhiyun static int vhci_send_cmd_unlink(struct vhci_device *vdev)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	struct vhci_unlink *unlink = NULL;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	struct msghdr msg;
192*4882a593Smuzhiyun 	struct kvec iov;
193*4882a593Smuzhiyun 	size_t txsize;
194*4882a593Smuzhiyun 	size_t total_size = 0;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) {
197*4882a593Smuzhiyun 		int ret;
198*4882a593Smuzhiyun 		struct usbip_header pdu_header;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 		memset(&pdu_header, 0, sizeof(pdu_header));
201*4882a593Smuzhiyun 		memset(&msg, 0, sizeof(msg));
202*4882a593Smuzhiyun 		memset(&iov, 0, sizeof(iov));
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 		usbip_dbg_vhci_tx("setup cmd unlink, %lu\n", unlink->seqnum);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 		/* 1. setup usbip_header */
207*4882a593Smuzhiyun 		pdu_header.base.command = USBIP_CMD_UNLINK;
208*4882a593Smuzhiyun 		pdu_header.base.seqnum  = unlink->seqnum;
209*4882a593Smuzhiyun 		pdu_header.base.devid	= vdev->devid;
210*4882a593Smuzhiyun 		pdu_header.base.ep	= 0;
211*4882a593Smuzhiyun 		pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 		usbip_header_correct_endian(&pdu_header, 1);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 		iov.iov_base = &pdu_header;
216*4882a593Smuzhiyun 		iov.iov_len  = sizeof(pdu_header);
217*4882a593Smuzhiyun 		txsize = sizeof(pdu_header);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 		ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, &iov, 1, txsize);
220*4882a593Smuzhiyun 		if (ret != txsize) {
221*4882a593Smuzhiyun 			pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
222*4882a593Smuzhiyun 			       txsize);
223*4882a593Smuzhiyun 			usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
224*4882a593Smuzhiyun 			return -1;
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 		usbip_dbg_vhci_tx("send txdata\n");
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 		total_size += txsize;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	return total_size;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
vhci_tx_loop(void * data)235*4882a593Smuzhiyun int vhci_tx_loop(void *data)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	struct usbip_device *ud = data;
238*4882a593Smuzhiyun 	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	while (!kthread_should_stop()) {
241*4882a593Smuzhiyun 		if (vhci_send_cmd_submit(vdev) < 0)
242*4882a593Smuzhiyun 			break;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 		if (vhci_send_cmd_unlink(vdev) < 0)
245*4882a593Smuzhiyun 			break;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 		wait_event_interruptible(vdev->waitq_tx,
248*4882a593Smuzhiyun 					 (!list_empty(&vdev->priv_tx) ||
249*4882a593Smuzhiyun 					  !list_empty(&vdev->unlink_tx) ||
250*4882a593Smuzhiyun 					  kthread_should_stop()));
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 		usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
253*4882a593Smuzhiyun 	}
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	return 0;
256*4882a593Smuzhiyun }
257