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