xref: /openbmc/linux/drivers/usb/usbip/vhci_rx.c (revision 260ea95c)
1 /*
2  * Copyright (C) 2003-2008 Takahiro Hirofuchi
3  *
4  * This is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17  * USA.
18  */
19 
20 #include <linux/kthread.h>
21 #include <linux/slab.h>
22 
23 #include "usbip_common.h"
24 #include "vhci.h"
25 
26 /* get URB from transmitted urb queue. caller must hold vdev->priv_lock */
27 struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum)
28 {
29 	struct vhci_priv *priv, *tmp;
30 	struct urb *urb = NULL;
31 	int status;
32 
33 	list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) {
34 		if (priv->seqnum != seqnum)
35 			continue;
36 
37 		urb = priv->urb;
38 		status = urb->status;
39 
40 		usbip_dbg_vhci_rx("find urb %p vurb %p seqnum %u\n",
41 				urb, priv, seqnum);
42 
43 		switch (status) {
44 		case -ENOENT:
45 			/* fall through */
46 		case -ECONNRESET:
47 			dev_info(&urb->dev->dev,
48 				 "urb %p was unlinked %ssynchronuously.\n", urb,
49 				 status == -ENOENT ? "" : "a");
50 			break;
51 		case -EINPROGRESS:
52 			/* no info output */
53 			break;
54 		default:
55 			dev_info(&urb->dev->dev,
56 				 "urb %p may be in a error, status %d\n", urb,
57 				 status);
58 		}
59 
60 		list_del(&priv->list);
61 		kfree(priv);
62 		urb->hcpriv = NULL;
63 
64 		break;
65 	}
66 
67 	return urb;
68 }
69 
70 static void vhci_recv_ret_submit(struct vhci_device *vdev,
71 				 struct usbip_header *pdu)
72 {
73 	struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
74 	struct vhci *vhci = vhci_hcd->vhci;
75 	struct usbip_device *ud = &vdev->ud;
76 	struct urb *urb;
77 	unsigned long flags;
78 
79 	spin_lock_irqsave(&vdev->priv_lock, flags);
80 	urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
81 	spin_unlock_irqrestore(&vdev->priv_lock, flags);
82 
83 	if (!urb) {
84 		pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
85 		pr_info("max seqnum %d\n",
86 			atomic_read(&vhci_hcd->seqnum));
87 		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
88 		return;
89 	}
90 
91 	/* unpack the pdu to a urb */
92 	usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
93 
94 	/* recv transfer buffer */
95 	if (usbip_recv_xbuff(ud, urb) < 0)
96 		return;
97 
98 	/* recv iso_packet_descriptor */
99 	if (usbip_recv_iso(ud, urb) < 0)
100 		return;
101 
102 	/* restore the padding in iso packets */
103 	usbip_pad_iso(ud, urb);
104 
105 	if (usbip_dbg_flag_vhci_rx)
106 		usbip_dump_urb(urb);
107 
108 	usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
109 
110 	spin_lock_irqsave(&vhci->lock, flags);
111 	usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci_hcd), urb);
112 	spin_unlock_irqrestore(&vhci->lock, flags);
113 
114 	usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci_hcd), urb, urb->status);
115 
116 	usbip_dbg_vhci_rx("Leave\n");
117 }
118 
119 static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
120 						  struct usbip_header *pdu)
121 {
122 	struct vhci_unlink *unlink, *tmp;
123 	unsigned long flags;
124 
125 	spin_lock_irqsave(&vdev->priv_lock, flags);
126 
127 	list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
128 		pr_info("unlink->seqnum %lu\n", unlink->seqnum);
129 		if (unlink->seqnum == pdu->base.seqnum) {
130 			usbip_dbg_vhci_rx("found pending unlink, %lu\n",
131 					  unlink->seqnum);
132 			list_del(&unlink->list);
133 
134 			spin_unlock_irqrestore(&vdev->priv_lock, flags);
135 			return unlink;
136 		}
137 	}
138 
139 	spin_unlock_irqrestore(&vdev->priv_lock, flags);
140 
141 	return NULL;
142 }
143 
144 static void vhci_recv_ret_unlink(struct vhci_device *vdev,
145 				 struct usbip_header *pdu)
146 {
147 	struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
148 	struct vhci *vhci = vhci_hcd->vhci;
149 	struct vhci_unlink *unlink;
150 	struct urb *urb;
151 	unsigned long flags;
152 
153 	usbip_dump_header(pdu);
154 
155 	unlink = dequeue_pending_unlink(vdev, pdu);
156 	if (!unlink) {
157 		pr_info("cannot find the pending unlink %u\n",
158 			pdu->base.seqnum);
159 		return;
160 	}
161 
162 	spin_lock_irqsave(&vdev->priv_lock, flags);
163 	urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
164 	spin_unlock_irqrestore(&vdev->priv_lock, flags);
165 
166 	if (!urb) {
167 		/*
168 		 * I get the result of a unlink request. But, it seems that I
169 		 * already received the result of its submit result and gave
170 		 * back the URB.
171 		 */
172 		pr_info("the urb (seqnum %d) was already given back\n",
173 			pdu->base.seqnum);
174 	} else {
175 		usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
176 
177 		/* If unlink is successful, status is -ECONNRESET */
178 		urb->status = pdu->u.ret_unlink.status;
179 		pr_info("urb->status %d\n", urb->status);
180 
181 		spin_lock_irqsave(&vhci->lock, flags);
182 		usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci_hcd), urb);
183 		spin_unlock_irqrestore(&vhci->lock, flags);
184 
185 		usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci_hcd), urb, urb->status);
186 	}
187 
188 	kfree(unlink);
189 }
190 
191 static int vhci_priv_tx_empty(struct vhci_device *vdev)
192 {
193 	int empty = 0;
194 	unsigned long flags;
195 
196 	spin_lock_irqsave(&vdev->priv_lock, flags);
197 	empty = list_empty(&vdev->priv_rx);
198 	spin_unlock_irqrestore(&vdev->priv_lock, flags);
199 
200 	return empty;
201 }
202 
203 /* recv a pdu */
204 static void vhci_rx_pdu(struct usbip_device *ud)
205 {
206 	int ret;
207 	struct usbip_header pdu;
208 	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
209 
210 	usbip_dbg_vhci_rx("Enter\n");
211 
212 	memset(&pdu, 0, sizeof(pdu));
213 
214 	/* receive a pdu header */
215 	ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
216 	if (ret < 0) {
217 		if (ret == -ECONNRESET)
218 			pr_info("connection reset by peer\n");
219 		else if (ret == -EAGAIN) {
220 			/* ignore if connection was idle */
221 			if (vhci_priv_tx_empty(vdev))
222 				return;
223 			pr_info("connection timed out with pending urbs\n");
224 		} else if (ret != -ERESTARTSYS)
225 			pr_info("xmit failed %d\n", ret);
226 
227 		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
228 		return;
229 	}
230 	if (ret == 0) {
231 		pr_info("connection closed");
232 		usbip_event_add(ud, VDEV_EVENT_DOWN);
233 		return;
234 	}
235 	if (ret != sizeof(pdu)) {
236 		pr_err("received pdu size is %d, should be %d\n", ret,
237 		       (unsigned int)sizeof(pdu));
238 		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
239 		return;
240 	}
241 
242 	usbip_header_correct_endian(&pdu, 0);
243 
244 	if (usbip_dbg_flag_vhci_rx)
245 		usbip_dump_header(&pdu);
246 
247 	switch (pdu.base.command) {
248 	case USBIP_RET_SUBMIT:
249 		vhci_recv_ret_submit(vdev, &pdu);
250 		break;
251 	case USBIP_RET_UNLINK:
252 		vhci_recv_ret_unlink(vdev, &pdu);
253 		break;
254 	default:
255 		/* NOT REACHED */
256 		pr_err("unknown pdu %u\n", pdu.base.command);
257 		usbip_dump_header(&pdu);
258 		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
259 		break;
260 	}
261 }
262 
263 int vhci_rx_loop(void *data)
264 {
265 	struct usbip_device *ud = data;
266 
267 	while (!kthread_should_stop()) {
268 		if (usbip_event_happened(ud))
269 			break;
270 
271 		vhci_rx_pdu(ud);
272 	}
273 
274 	return 0;
275 }
276