root/drivers/usb/usbip/vudc_rx.c

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

DEFINITIONS

This source file includes following definitions.
  1. alloc_urb_from_cmd
  2. v_recv_cmd_unlink
  3. v_recv_cmd_submit
  4. v_rx_pdu
  5. v_rx_loop

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
   4  * Copyright (C) 2015-2016 Samsung Electronics
   5  *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
   6  */
   7 
   8 #include <net/sock.h>
   9 #include <linux/list.h>
  10 #include <linux/kthread.h>
  11 
  12 #include "usbip_common.h"
  13 #include "vudc.h"
  14 
  15 static int alloc_urb_from_cmd(struct urb **urbp,
  16                               struct usbip_header *pdu, u8 type)
  17 {
  18         struct urb *urb;
  19 
  20         if (type == USB_ENDPOINT_XFER_ISOC)
  21                 urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets,
  22                                           GFP_KERNEL);
  23         else
  24                 urb = usb_alloc_urb(0, GFP_KERNEL);
  25 
  26         if (!urb)
  27                 goto err;
  28 
  29         usbip_pack_pdu(pdu, urb, USBIP_CMD_SUBMIT, 0);
  30 
  31         if (urb->transfer_buffer_length > 0) {
  32                 urb->transfer_buffer = kzalloc(urb->transfer_buffer_length,
  33                         GFP_KERNEL);
  34                 if (!urb->transfer_buffer)
  35                         goto free_urb;
  36         }
  37 
  38         urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8,
  39                             GFP_KERNEL);
  40         if (!urb->setup_packet)
  41                 goto free_buffer;
  42 
  43         /*
  44          * FIXME - we only setup pipe enough for usbip functions
  45          * to behave nicely
  46          */
  47         urb->pipe |= pdu->base.direction == USBIP_DIR_IN ?
  48                         USB_DIR_IN : USB_DIR_OUT;
  49 
  50         *urbp = urb;
  51         return 0;
  52 
  53 free_buffer:
  54         kfree(urb->transfer_buffer);
  55         urb->transfer_buffer = NULL;
  56 free_urb:
  57         usb_free_urb(urb);
  58 err:
  59         return -ENOMEM;
  60 }
  61 
  62 static int v_recv_cmd_unlink(struct vudc *udc,
  63                                 struct usbip_header *pdu)
  64 {
  65         unsigned long flags;
  66         struct urbp *urb_p;
  67 
  68         spin_lock_irqsave(&udc->lock, flags);
  69         list_for_each_entry(urb_p, &udc->urb_queue, urb_entry) {
  70                 if (urb_p->seqnum != pdu->u.cmd_unlink.seqnum)
  71                         continue;
  72                 urb_p->urb->unlinked = -ECONNRESET;
  73                 urb_p->seqnum = pdu->base.seqnum;
  74                 v_kick_timer(udc, jiffies);
  75                 spin_unlock_irqrestore(&udc->lock, flags);
  76                 return 0;
  77         }
  78         /* Not found, completed / not queued */
  79         spin_lock(&udc->lock_tx);
  80         v_enqueue_ret_unlink(udc, pdu->base.seqnum, 0);
  81         wake_up(&udc->tx_waitq);
  82         spin_unlock(&udc->lock_tx);
  83         spin_unlock_irqrestore(&udc->lock, flags);
  84 
  85         return 0;
  86 }
  87 
  88 static int v_recv_cmd_submit(struct vudc *udc,
  89                                  struct usbip_header *pdu)
  90 {
  91         int ret = 0;
  92         struct urbp *urb_p;
  93         u8 address;
  94         unsigned long flags;
  95 
  96         urb_p = alloc_urbp();
  97         if (!urb_p) {
  98                 usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_MALLOC);
  99                 return -ENOMEM;
 100         }
 101 
 102         /* base.ep is pipeendpoint(pipe) */
 103         address = pdu->base.ep;
 104         if (pdu->base.direction == USBIP_DIR_IN)
 105                 address |= USB_DIR_IN;
 106 
 107         spin_lock_irq(&udc->lock);
 108         urb_p->ep = vudc_find_endpoint(udc, address);
 109         if (!urb_p->ep) {
 110                 /* we don't know the type, there may be isoc data! */
 111                 dev_err(&udc->pdev->dev, "request to nonexistent endpoint");
 112                 spin_unlock_irq(&udc->lock);
 113                 usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_TCP);
 114                 ret = -EPIPE;
 115                 goto free_urbp;
 116         }
 117         urb_p->type = urb_p->ep->type;
 118         spin_unlock_irq(&udc->lock);
 119 
 120         urb_p->new = 1;
 121         urb_p->seqnum = pdu->base.seqnum;
 122 
 123         if (urb_p->ep->type == USB_ENDPOINT_XFER_ISOC) {
 124                 /* validate packet size and number of packets */
 125                 unsigned int maxp, packets, bytes;
 126 
 127                 maxp = usb_endpoint_maxp(urb_p->ep->desc);
 128                 maxp *= usb_endpoint_maxp_mult(urb_p->ep->desc);
 129                 bytes = pdu->u.cmd_submit.transfer_buffer_length;
 130                 packets = DIV_ROUND_UP(bytes, maxp);
 131 
 132                 if (pdu->u.cmd_submit.number_of_packets < 0 ||
 133                     pdu->u.cmd_submit.number_of_packets > packets) {
 134                         dev_err(&udc->gadget.dev,
 135                                 "CMD_SUBMIT: isoc invalid num packets %d\n",
 136                                 pdu->u.cmd_submit.number_of_packets);
 137                         ret = -EMSGSIZE;
 138                         goto free_urbp;
 139                 }
 140         }
 141 
 142         ret = alloc_urb_from_cmd(&urb_p->urb, pdu, urb_p->ep->type);
 143         if (ret) {
 144                 usbip_event_add(&udc->ud, VUDC_EVENT_ERROR_MALLOC);
 145                 ret = -ENOMEM;
 146                 goto free_urbp;
 147         }
 148 
 149         urb_p->urb->status = -EINPROGRESS;
 150 
 151         /* FIXME: more pipe setup to please usbip_common */
 152         urb_p->urb->pipe &= ~(3 << 30);
 153         switch (urb_p->ep->type) {
 154         case USB_ENDPOINT_XFER_BULK:
 155                 urb_p->urb->pipe |= (PIPE_BULK << 30);
 156                 break;
 157         case USB_ENDPOINT_XFER_INT:
 158                 urb_p->urb->pipe |= (PIPE_INTERRUPT << 30);
 159                 break;
 160         case USB_ENDPOINT_XFER_CONTROL:
 161                 urb_p->urb->pipe |= (PIPE_CONTROL << 30);
 162                 break;
 163         case USB_ENDPOINT_XFER_ISOC:
 164                 urb_p->urb->pipe |= (PIPE_ISOCHRONOUS << 30);
 165                 break;
 166         }
 167         ret = usbip_recv_xbuff(&udc->ud, urb_p->urb);
 168         if (ret < 0)
 169                 goto free_urbp;
 170 
 171         ret = usbip_recv_iso(&udc->ud, urb_p->urb);
 172         if (ret < 0)
 173                 goto free_urbp;
 174 
 175         spin_lock_irqsave(&udc->lock, flags);
 176         v_kick_timer(udc, jiffies);
 177         list_add_tail(&urb_p->urb_entry, &udc->urb_queue);
 178         spin_unlock_irqrestore(&udc->lock, flags);
 179 
 180         return 0;
 181 
 182 free_urbp:
 183         free_urbp_and_urb(urb_p);
 184         return ret;
 185 }
 186 
 187 static int v_rx_pdu(struct usbip_device *ud)
 188 {
 189         int ret;
 190         struct usbip_header pdu;
 191         struct vudc *udc = container_of(ud, struct vudc, ud);
 192 
 193         memset(&pdu, 0, sizeof(pdu));
 194         ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
 195         if (ret != sizeof(pdu)) {
 196                 usbip_event_add(ud, VUDC_EVENT_ERROR_TCP);
 197                 if (ret >= 0)
 198                         return -EPIPE;
 199                 return ret;
 200         }
 201         usbip_header_correct_endian(&pdu, 0);
 202 
 203         spin_lock_irq(&ud->lock);
 204         ret = (ud->status == SDEV_ST_USED);
 205         spin_unlock_irq(&ud->lock);
 206         if (!ret) {
 207                 usbip_event_add(ud, VUDC_EVENT_ERROR_TCP);
 208                 return -EBUSY;
 209         }
 210 
 211         switch (pdu.base.command) {
 212         case USBIP_CMD_UNLINK:
 213                 ret = v_recv_cmd_unlink(udc, &pdu);
 214                 break;
 215         case USBIP_CMD_SUBMIT:
 216                 ret = v_recv_cmd_submit(udc, &pdu);
 217                 break;
 218         default:
 219                 ret = -EPIPE;
 220                 pr_err("rx: unknown command");
 221                 break;
 222         }
 223         return ret;
 224 }
 225 
 226 int v_rx_loop(void *data)
 227 {
 228         struct usbip_device *ud = data;
 229         int ret = 0;
 230 
 231         while (!kthread_should_stop()) {
 232                 if (usbip_event_happened(ud))
 233                         break;
 234                 ret = v_rx_pdu(ud);
 235                 if (ret < 0) {
 236                         pr_warn("v_rx exit with error %d", ret);
 237                         break;
 238                 }
 239         }
 240         return ret;
 241 }

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