vudc_rx.c (5539B)
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 15static 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 53free_buffer: 54 kfree(urb->transfer_buffer); 55 urb->transfer_buffer = NULL; 56free_urb: 57 usb_free_urb(urb); 58err: 59 return -ENOMEM; 60} 61 62static 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 88static 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 182free_urbp: 183 free_urbp_and_urb(urb_p); 184 return ret; 185} 186 187static 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 226int 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}