root/drivers/usb/usbip/vhci_rx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pickup_urb_and_free_priv
  2. vhci_recv_ret_submit
  3. dequeue_pending_unlink
  4. vhci_recv_ret_unlink
  5. vhci_priv_tx_empty
  6. vhci_rx_pdu
  7. vhci_rx_loop

   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 */
  13 struct 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                         /* fall through */
  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 
  55 static 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 
  94 error:
  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 
 112 static 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 
 137 static 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 
 184 static 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 */
 197 static 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 
 256 int 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                 vhci_rx_pdu(ud);
 265         }
 266 
 267         return 0;
 268 }

/* [<][>][^][v][top][bottom][index][help] */