18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2003-2008 Takahiro Hirofuchi 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kthread.h> 78c2ecf20Sopenharmony_ci#include <linux/socket.h> 88c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "usbip_common.h" 118c2ecf20Sopenharmony_ci#include "stub.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ 148c2ecf20Sopenharmony_civoid stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, 158c2ecf20Sopenharmony_ci __u32 status) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct stub_unlink *unlink; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC); 208c2ecf20Sopenharmony_ci if (!unlink) { 218c2ecf20Sopenharmony_ci usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC); 228c2ecf20Sopenharmony_ci return; 238c2ecf20Sopenharmony_ci } 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci unlink->seqnum = seqnum; 268c2ecf20Sopenharmony_ci unlink->status = status; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci list_add_tail(&unlink->list, &sdev->unlink_tx); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/** 328c2ecf20Sopenharmony_ci * stub_complete - completion handler of a usbip urb 338c2ecf20Sopenharmony_ci * @urb: pointer to the urb completed 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * When a urb has completed, the USB core driver calls this function mostly in 368c2ecf20Sopenharmony_ci * the interrupt context. To return the result of a urb, the completed urb is 378c2ecf20Sopenharmony_ci * linked to the pending list of returning. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_civoid stub_complete(struct urb *urb) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci struct stub_priv *priv = (struct stub_priv *) urb->context; 438c2ecf20Sopenharmony_ci struct stub_device *sdev = priv->sdev; 448c2ecf20Sopenharmony_ci unsigned long flags; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci usbip_dbg_stub_tx("complete! status %d\n", urb->status); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci switch (urb->status) { 498c2ecf20Sopenharmony_ci case 0: 508c2ecf20Sopenharmony_ci /* OK */ 518c2ecf20Sopenharmony_ci break; 528c2ecf20Sopenharmony_ci case -ENOENT: 538c2ecf20Sopenharmony_ci dev_info(&urb->dev->dev, 548c2ecf20Sopenharmony_ci "stopped by a call to usb_kill_urb() because of cleaning up a virtual connection\n"); 558c2ecf20Sopenharmony_ci return; 568c2ecf20Sopenharmony_ci case -ECONNRESET: 578c2ecf20Sopenharmony_ci dev_info(&urb->dev->dev, 588c2ecf20Sopenharmony_ci "unlinked by a call to usb_unlink_urb()\n"); 598c2ecf20Sopenharmony_ci break; 608c2ecf20Sopenharmony_ci case -EPIPE: 618c2ecf20Sopenharmony_ci dev_info(&urb->dev->dev, "endpoint %d is stalled\n", 628c2ecf20Sopenharmony_ci usb_pipeendpoint(urb->pipe)); 638c2ecf20Sopenharmony_ci break; 648c2ecf20Sopenharmony_ci case -ESHUTDOWN: 658c2ecf20Sopenharmony_ci dev_info(&urb->dev->dev, "device removed?\n"); 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci default: 688c2ecf20Sopenharmony_ci dev_info(&urb->dev->dev, 698c2ecf20Sopenharmony_ci "urb completion with non-zero status %d\n", 708c2ecf20Sopenharmony_ci urb->status); 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * If the server breaks single SG request into the several URBs, the 768c2ecf20Sopenharmony_ci * URBs must be reassembled before sending completed URB to the vhci. 778c2ecf20Sopenharmony_ci * Don't wake up the tx thread until all the URBs are completed. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci if (priv->sgl) { 808c2ecf20Sopenharmony_ci priv->completed_urbs++; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* Only save the first error status */ 838c2ecf20Sopenharmony_ci if (urb->status && !priv->urb_status) 848c2ecf20Sopenharmony_ci priv->urb_status = urb->status; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (priv->completed_urbs < priv->num_urbs) 878c2ecf20Sopenharmony_ci return; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* link a urb to the queue of tx. */ 918c2ecf20Sopenharmony_ci spin_lock_irqsave(&sdev->priv_lock, flags); 928c2ecf20Sopenharmony_ci if (sdev->ud.tcp_socket == NULL) { 938c2ecf20Sopenharmony_ci usbip_dbg_stub_tx("ignore urb for closed connection\n"); 948c2ecf20Sopenharmony_ci /* It will be freed in stub_device_cleanup_urbs(). */ 958c2ecf20Sopenharmony_ci } else if (priv->unlinking) { 968c2ecf20Sopenharmony_ci stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status); 978c2ecf20Sopenharmony_ci stub_free_priv_and_urb(priv); 988c2ecf20Sopenharmony_ci } else { 998c2ecf20Sopenharmony_ci list_move_tail(&priv->list, &sdev->priv_tx); 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* wake up tx_thread */ 1048c2ecf20Sopenharmony_ci wake_up(&sdev->tx_waitq); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic inline void setup_base_pdu(struct usbip_header_basic *base, 1088c2ecf20Sopenharmony_ci __u32 command, __u32 seqnum) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci base->command = command; 1118c2ecf20Sopenharmony_ci base->seqnum = seqnum; 1128c2ecf20Sopenharmony_ci base->devid = 0; 1138c2ecf20Sopenharmony_ci base->ep = 0; 1148c2ecf20Sopenharmony_ci base->direction = 0; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct stub_priv *priv = (struct stub_priv *) urb->context; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum); 1228c2ecf20Sopenharmony_ci usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void setup_ret_unlink_pdu(struct usbip_header *rpdu, 1268c2ecf20Sopenharmony_ci struct stub_unlink *unlink) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); 1298c2ecf20Sopenharmony_ci rpdu->u.ret_unlink.status = unlink->status; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci unsigned long flags; 1358c2ecf20Sopenharmony_ci struct stub_priv *priv, *tmp; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci spin_lock_irqsave(&sdev->priv_lock, flags); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) { 1408c2ecf20Sopenharmony_ci list_move_tail(&priv->list, &sdev->priv_free); 1418c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 1428c2ecf20Sopenharmony_ci return priv; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci return NULL; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic int stub_send_ret_submit(struct stub_device *sdev) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci unsigned long flags; 1538c2ecf20Sopenharmony_ci struct stub_priv *priv, *tmp; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci struct msghdr msg; 1568c2ecf20Sopenharmony_ci size_t txsize; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci size_t total_size = 0; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { 1618c2ecf20Sopenharmony_ci struct urb *urb = priv->urbs[0]; 1628c2ecf20Sopenharmony_ci struct usbip_header pdu_header; 1638c2ecf20Sopenharmony_ci struct usbip_iso_packet_descriptor *iso_buffer = NULL; 1648c2ecf20Sopenharmony_ci struct kvec *iov = NULL; 1658c2ecf20Sopenharmony_ci struct scatterlist *sg; 1668c2ecf20Sopenharmony_ci u32 actual_length = 0; 1678c2ecf20Sopenharmony_ci int iovnum = 0; 1688c2ecf20Sopenharmony_ci int ret; 1698c2ecf20Sopenharmony_ci int i; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci txsize = 0; 1728c2ecf20Sopenharmony_ci memset(&pdu_header, 0, sizeof(pdu_header)); 1738c2ecf20Sopenharmony_ci memset(&msg, 0, sizeof(msg)); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (urb->actual_length > 0 && !urb->transfer_buffer && 1768c2ecf20Sopenharmony_ci !urb->num_sgs) { 1778c2ecf20Sopenharmony_ci dev_err(&sdev->udev->dev, 1788c2ecf20Sopenharmony_ci "urb: actual_length %d transfer_buffer null\n", 1798c2ecf20Sopenharmony_ci urb->actual_length); 1808c2ecf20Sopenharmony_ci return -1; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) 1848c2ecf20Sopenharmony_ci iovnum = 2 + urb->number_of_packets; 1858c2ecf20Sopenharmony_ci else if (usb_pipein(urb->pipe) && urb->actual_length > 0 && 1868c2ecf20Sopenharmony_ci urb->num_sgs) 1878c2ecf20Sopenharmony_ci iovnum = 1 + urb->num_sgs; 1888c2ecf20Sopenharmony_ci else if (usb_pipein(urb->pipe) && priv->sgl) 1898c2ecf20Sopenharmony_ci iovnum = 1 + priv->num_urbs; 1908c2ecf20Sopenharmony_ci else 1918c2ecf20Sopenharmony_ci iovnum = 2; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci iov = kcalloc(iovnum, sizeof(struct kvec), GFP_KERNEL); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (!iov) { 1968c2ecf20Sopenharmony_ci usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); 1978c2ecf20Sopenharmony_ci return -1; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci iovnum = 0; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* 1. setup usbip_header */ 2038c2ecf20Sopenharmony_ci setup_ret_submit_pdu(&pdu_header, urb); 2048c2ecf20Sopenharmony_ci usbip_dbg_stub_tx("setup txdata seqnum: %d\n", 2058c2ecf20Sopenharmony_ci pdu_header.base.seqnum); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if (priv->sgl) { 2088c2ecf20Sopenharmony_ci for (i = 0; i < priv->num_urbs; i++) 2098c2ecf20Sopenharmony_ci actual_length += priv->urbs[i]->actual_length; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci pdu_header.u.ret_submit.status = priv->urb_status; 2128c2ecf20Sopenharmony_ci pdu_header.u.ret_submit.actual_length = actual_length; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci usbip_header_correct_endian(&pdu_header, 1); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci iov[iovnum].iov_base = &pdu_header; 2188c2ecf20Sopenharmony_ci iov[iovnum].iov_len = sizeof(pdu_header); 2198c2ecf20Sopenharmony_ci iovnum++; 2208c2ecf20Sopenharmony_ci txsize += sizeof(pdu_header); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* 2. setup transfer buffer */ 2238c2ecf20Sopenharmony_ci if (usb_pipein(urb->pipe) && priv->sgl) { 2248c2ecf20Sopenharmony_ci /* If the server split a single SG request into several 2258c2ecf20Sopenharmony_ci * URBs because the server's HCD doesn't support SG, 2268c2ecf20Sopenharmony_ci * reassemble the split URB buffers into a single 2278c2ecf20Sopenharmony_ci * return command. 2288c2ecf20Sopenharmony_ci */ 2298c2ecf20Sopenharmony_ci for (i = 0; i < priv->num_urbs; i++) { 2308c2ecf20Sopenharmony_ci iov[iovnum].iov_base = 2318c2ecf20Sopenharmony_ci priv->urbs[i]->transfer_buffer; 2328c2ecf20Sopenharmony_ci iov[iovnum].iov_len = 2338c2ecf20Sopenharmony_ci priv->urbs[i]->actual_length; 2348c2ecf20Sopenharmony_ci iovnum++; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci txsize += actual_length; 2378c2ecf20Sopenharmony_ci } else if (usb_pipein(urb->pipe) && 2388c2ecf20Sopenharmony_ci usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS && 2398c2ecf20Sopenharmony_ci urb->actual_length > 0) { 2408c2ecf20Sopenharmony_ci if (urb->num_sgs) { 2418c2ecf20Sopenharmony_ci unsigned int copy = urb->actual_length; 2428c2ecf20Sopenharmony_ci int size; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci for_each_sg(urb->sg, sg, urb->num_sgs, i) { 2458c2ecf20Sopenharmony_ci if (copy == 0) 2468c2ecf20Sopenharmony_ci break; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (copy < sg->length) 2498c2ecf20Sopenharmony_ci size = copy; 2508c2ecf20Sopenharmony_ci else 2518c2ecf20Sopenharmony_ci size = sg->length; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci iov[iovnum].iov_base = sg_virt(sg); 2548c2ecf20Sopenharmony_ci iov[iovnum].iov_len = size; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci iovnum++; 2578c2ecf20Sopenharmony_ci copy -= size; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci } else { 2608c2ecf20Sopenharmony_ci iov[iovnum].iov_base = urb->transfer_buffer; 2618c2ecf20Sopenharmony_ci iov[iovnum].iov_len = urb->actual_length; 2628c2ecf20Sopenharmony_ci iovnum++; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci txsize += urb->actual_length; 2658c2ecf20Sopenharmony_ci } else if (usb_pipein(urb->pipe) && 2668c2ecf20Sopenharmony_ci usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { 2678c2ecf20Sopenharmony_ci /* 2688c2ecf20Sopenharmony_ci * For isochronous packets: actual length is the sum of 2698c2ecf20Sopenharmony_ci * the actual length of the individual, packets, but as 2708c2ecf20Sopenharmony_ci * the packet offsets are not changed there will be 2718c2ecf20Sopenharmony_ci * padding between the packets. To optimally use the 2728c2ecf20Sopenharmony_ci * bandwidth the padding is not transmitted. 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci int i; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 2788c2ecf20Sopenharmony_ci iov[iovnum].iov_base = urb->transfer_buffer + 2798c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].offset; 2808c2ecf20Sopenharmony_ci iov[iovnum].iov_len = 2818c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].actual_length; 2828c2ecf20Sopenharmony_ci iovnum++; 2838c2ecf20Sopenharmony_ci txsize += urb->iso_frame_desc[i].actual_length; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (txsize != sizeof(pdu_header) + urb->actual_length) { 2878c2ecf20Sopenharmony_ci dev_err(&sdev->udev->dev, 2888c2ecf20Sopenharmony_ci "actual length of urb %d does not match iso packet sizes %zu\n", 2898c2ecf20Sopenharmony_ci urb->actual_length, 2908c2ecf20Sopenharmony_ci txsize-sizeof(pdu_header)); 2918c2ecf20Sopenharmony_ci kfree(iov); 2928c2ecf20Sopenharmony_ci usbip_event_add(&sdev->ud, 2938c2ecf20Sopenharmony_ci SDEV_EVENT_ERROR_TCP); 2948c2ecf20Sopenharmony_ci return -1; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* 3. setup iso_packet_descriptor */ 2998c2ecf20Sopenharmony_ci if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { 3008c2ecf20Sopenharmony_ci ssize_t len = 0; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); 3038c2ecf20Sopenharmony_ci if (!iso_buffer) { 3048c2ecf20Sopenharmony_ci usbip_event_add(&sdev->ud, 3058c2ecf20Sopenharmony_ci SDEV_EVENT_ERROR_MALLOC); 3068c2ecf20Sopenharmony_ci kfree(iov); 3078c2ecf20Sopenharmony_ci return -1; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci iov[iovnum].iov_base = iso_buffer; 3118c2ecf20Sopenharmony_ci iov[iovnum].iov_len = len; 3128c2ecf20Sopenharmony_ci txsize += len; 3138c2ecf20Sopenharmony_ci iovnum++; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, 3178c2ecf20Sopenharmony_ci iov, iovnum, txsize); 3188c2ecf20Sopenharmony_ci if (ret != txsize) { 3198c2ecf20Sopenharmony_ci dev_err(&sdev->udev->dev, 3208c2ecf20Sopenharmony_ci "sendmsg failed!, retval %d for %zd\n", 3218c2ecf20Sopenharmony_ci ret, txsize); 3228c2ecf20Sopenharmony_ci kfree(iov); 3238c2ecf20Sopenharmony_ci kfree(iso_buffer); 3248c2ecf20Sopenharmony_ci usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); 3258c2ecf20Sopenharmony_ci return -1; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci kfree(iov); 3298c2ecf20Sopenharmony_ci kfree(iso_buffer); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci total_size += txsize; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci spin_lock_irqsave(&sdev->priv_lock, flags); 3358c2ecf20Sopenharmony_ci list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { 3368c2ecf20Sopenharmony_ci stub_free_priv_and_urb(priv); 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci return total_size; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci unsigned long flags; 3468c2ecf20Sopenharmony_ci struct stub_unlink *unlink, *tmp; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci spin_lock_irqsave(&sdev->priv_lock, flags); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { 3518c2ecf20Sopenharmony_ci list_move_tail(&unlink->list, &sdev->unlink_free); 3528c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 3538c2ecf20Sopenharmony_ci return unlink; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return NULL; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic int stub_send_ret_unlink(struct stub_device *sdev) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci unsigned long flags; 3648c2ecf20Sopenharmony_ci struct stub_unlink *unlink, *tmp; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci struct msghdr msg; 3678c2ecf20Sopenharmony_ci struct kvec iov[1]; 3688c2ecf20Sopenharmony_ci size_t txsize; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci size_t total_size = 0; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) { 3738c2ecf20Sopenharmony_ci int ret; 3748c2ecf20Sopenharmony_ci struct usbip_header pdu_header; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci txsize = 0; 3778c2ecf20Sopenharmony_ci memset(&pdu_header, 0, sizeof(pdu_header)); 3788c2ecf20Sopenharmony_ci memset(&msg, 0, sizeof(msg)); 3798c2ecf20Sopenharmony_ci memset(&iov, 0, sizeof(iov)); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci usbip_dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* 1. setup usbip_header */ 3848c2ecf20Sopenharmony_ci setup_ret_unlink_pdu(&pdu_header, unlink); 3858c2ecf20Sopenharmony_ci usbip_header_correct_endian(&pdu_header, 1); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci iov[0].iov_base = &pdu_header; 3888c2ecf20Sopenharmony_ci iov[0].iov_len = sizeof(pdu_header); 3898c2ecf20Sopenharmony_ci txsize += sizeof(pdu_header); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 3928c2ecf20Sopenharmony_ci 1, txsize); 3938c2ecf20Sopenharmony_ci if (ret != txsize) { 3948c2ecf20Sopenharmony_ci dev_err(&sdev->udev->dev, 3958c2ecf20Sopenharmony_ci "sendmsg failed!, retval %d for %zd\n", 3968c2ecf20Sopenharmony_ci ret, txsize); 3978c2ecf20Sopenharmony_ci usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); 3988c2ecf20Sopenharmony_ci return -1; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci usbip_dbg_stub_tx("send txdata\n"); 4028c2ecf20Sopenharmony_ci total_size += txsize; 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci spin_lock_irqsave(&sdev->priv_lock, flags); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { 4088c2ecf20Sopenharmony_ci list_del(&unlink->list); 4098c2ecf20Sopenharmony_ci kfree(unlink); 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sdev->priv_lock, flags); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci return total_size; 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ciint stub_tx_loop(void *data) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci struct usbip_device *ud = data; 4208c2ecf20Sopenharmony_ci struct stub_device *sdev = container_of(ud, struct stub_device, ud); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci while (!kthread_should_stop()) { 4238c2ecf20Sopenharmony_ci if (usbip_event_happened(ud)) 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* 4278c2ecf20Sopenharmony_ci * send_ret_submit comes earlier than send_ret_unlink. stub_rx 4288c2ecf20Sopenharmony_ci * looks at only priv_init queue. If the completion of a URB is 4298c2ecf20Sopenharmony_ci * earlier than the receive of CMD_UNLINK, priv is moved to 4308c2ecf20Sopenharmony_ci * priv_tx queue and stub_rx does not find the target priv. In 4318c2ecf20Sopenharmony_ci * this case, vhci_rx receives the result of the submit request 4328c2ecf20Sopenharmony_ci * and then receives the result of the unlink request. The 4338c2ecf20Sopenharmony_ci * result of the submit is given back to the usbcore as the 4348c2ecf20Sopenharmony_ci * completion of the unlink request. The request of the 4358c2ecf20Sopenharmony_ci * unlink is ignored. This is ok because a driver who calls 4368c2ecf20Sopenharmony_ci * usb_unlink_urb() understands the unlink was too late by 4378c2ecf20Sopenharmony_ci * getting the status of the given-backed URB which has the 4388c2ecf20Sopenharmony_ci * status of usb_submit_urb(). 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci if (stub_send_ret_submit(sdev) < 0) 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci if (stub_send_ret_unlink(sdev) < 0) 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci wait_event_interruptible(sdev->tx_waitq, 4478c2ecf20Sopenharmony_ci (!list_empty(&sdev->priv_tx) || 4488c2ecf20Sopenharmony_ci !list_empty(&sdev->unlink_tx) || 4498c2ecf20Sopenharmony_ci kthread_should_stop())); 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci return 0; 4538c2ecf20Sopenharmony_ci} 454