usbip_dbg_stub_tx("complete! status %d\n", urb->status);
switch (urb->status) { case0: /* OK */ break; case -ENOENT:
dev_info(&urb->dev->dev, "stopped by a call to usb_kill_urb() because of cleaning up a virtual connection\n"); return; case -ECONNRESET:
dev_info(&urb->dev->dev, "unlinked by a call to usb_unlink_urb()\n"); break; case -EPIPE:
dev_info(&urb->dev->dev, "endpoint %d is stalled\n",
usb_pipeendpoint(urb->pipe)); break; case -ESHUTDOWN:
dev_info(&urb->dev->dev, "device removed?\n"); break; default:
dev_info(&urb->dev->dev, "urb completion with non-zero status %d\n",
urb->status); break;
}
/* *IftheserverbreakssingleSGrequestintotheseveralURBs,the *URBsmustbereassembledbeforesendingcompletedURBtothevhci. *Don'twakeupthetxthreaduntilalltheURBsarecompleted.
*/ if (priv->sgl) {
priv->completed_urbs++;
/* Only save the first error status */ if (urb->status && !priv->urb_status)
priv->urb_status = urb->status;
if (priv->completed_urbs < priv->num_urbs) return;
}
/* link a urb to the queue of tx. */
spin_lock_irqsave(&sdev->priv_lock, flags); if (sdev->ud.tcp_socket == NULL) {
usbip_dbg_stub_tx("ignore urb for closed connection\n"); /* It will be freed in stub_device_cleanup_urbs(). */
} elseif (priv->unlinking) {
stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status);
stub_free_priv_and_urb(priv);
} else {
list_move_tail(&priv->list, &sdev->priv_tx);
}
spin_unlock_irqrestore(&sdev->priv_lock, flags);
/* wake up tx_thread */
wake_up(&sdev->tx_waitq);
}
/* 2. setup transfer buffer */ if (usb_pipein(urb->pipe) && priv->sgl) { /* If the server split a single SG request into several *URBsbecausetheserver'sHCDdoesn'tsupportSG, *reassemblethesplitURBbuffersintoasingle *returncommand.
*/ for (i = 0; i < priv->num_urbs; i++) {
iov[iovnum].iov_base =
priv->urbs[i]->transfer_buffer;
iov[iovnum].iov_len =
priv->urbs[i]->actual_length;
iovnum++;
}
txsize += actual_length;
} elseif (usb_pipein(urb->pipe) &&
usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
urb->actual_length > 0) { if (urb->num_sgs) { unsignedint copy = urb->actual_length; int size;
for_each_sg(urb->sg, sg, urb->num_sgs, i) { if (copy == 0) break;
for (i = 0; i < urb->number_of_packets; i++) {
iov[iovnum].iov_base = urb->transfer_buffer +
urb->iso_frame_desc[i].offset;
iov[iovnum].iov_len =
urb->iso_frame_desc[i].actual_length;
iovnum++;
txsize += urb->iso_frame_desc[i].actual_length;
}
if (txsize != sizeof(pdu_header) + urb->actual_length) {
dev_err(&sdev->udev->dev, "actual length of urb %d does not match iso packet sizes %zu\n",
urb->actual_length,
txsize-sizeof(pdu_header));
kfree(iov);
usbip_event_add(&sdev->ud,
SDEV_EVENT_ERROR_TCP); return -1;
}
}
/* 3. setup iso_packet_descriptor */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
ssize_t len = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.