Statistics
| Branch: | Revision:

root / hw / usb / combined-packet.c @ afd347ab

History | View | Annotate | Download (6.4 kB)

1 a552a966 Hans de Goede
/*
2 a552a966 Hans de Goede
 * QEMU USB packet combining code (for input pipelining)
3 a552a966 Hans de Goede
 *
4 a552a966 Hans de Goede
 * Copyright(c) 2012 Red Hat, Inc.
5 a552a966 Hans de Goede
 *
6 a552a966 Hans de Goede
 * Red Hat Authors:
7 a552a966 Hans de Goede
 * Hans de Goede <hdegoede@redhat.com>
8 a552a966 Hans de Goede
 *
9 a552a966 Hans de Goede
 * This library is free software; you can redistribute it and/or
10 a552a966 Hans de Goede
 * modify it under the terms of the GNU Lesser General Public
11 a552a966 Hans de Goede
 * License as published by the Free Software Foundation; either
12 a552a966 Hans de Goede
 * version 2 of the License, or(at your option) any later version.
13 a552a966 Hans de Goede
 *
14 a552a966 Hans de Goede
 * This library is distributed in the hope that it will be useful,
15 a552a966 Hans de Goede
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 a552a966 Hans de Goede
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 a552a966 Hans de Goede
 * Lesser General Public License for more details.
18 a552a966 Hans de Goede
 *
19 a552a966 Hans de Goede
 * You should have received a copy of the GNU General Public License
20 a552a966 Hans de Goede
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 a552a966 Hans de Goede
 */
22 a552a966 Hans de Goede
#include "qemu-common.h"
23 a552a966 Hans de Goede
#include "hw/usb.h"
24 1de7afc9 Paolo Bonzini
#include "qemu/iov.h"
25 a552a966 Hans de Goede
#include "trace.h"
26 a552a966 Hans de Goede
27 a552a966 Hans de Goede
static void usb_combined_packet_add(USBCombinedPacket *combined, USBPacket *p)
28 a552a966 Hans de Goede
{
29 a552a966 Hans de Goede
    qemu_iovec_concat(&combined->iov, &p->iov, 0, p->iov.size);
30 a552a966 Hans de Goede
    QTAILQ_INSERT_TAIL(&combined->packets, p, combined_entry);
31 a552a966 Hans de Goede
    p->combined = combined;
32 a552a966 Hans de Goede
}
33 a552a966 Hans de Goede
34 ffd8a97f Hans de Goede
/* Note will free combined when the last packet gets removed */
35 a552a966 Hans de Goede
static void usb_combined_packet_remove(USBCombinedPacket *combined,
36 a552a966 Hans de Goede
                                       USBPacket *p)
37 a552a966 Hans de Goede
{
38 a552a966 Hans de Goede
    assert(p->combined == combined);
39 a552a966 Hans de Goede
    p->combined = NULL;
40 a552a966 Hans de Goede
    QTAILQ_REMOVE(&combined->packets, p, combined_entry);
41 ffd8a97f Hans de Goede
    if (QTAILQ_EMPTY(&combined->packets)) {
42 ffd8a97f Hans de Goede
        g_free(combined);
43 ffd8a97f Hans de Goede
    }
44 a552a966 Hans de Goede
}
45 a552a966 Hans de Goede
46 a552a966 Hans de Goede
/* Also handles completion of non combined packets for pipelined input eps */
47 a552a966 Hans de Goede
void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p)
48 a552a966 Hans de Goede
{
49 a552a966 Hans de Goede
    USBCombinedPacket *combined = p->combined;
50 a552a966 Hans de Goede
    USBEndpoint *ep = p->ep;
51 a552a966 Hans de Goede
    USBPacket *next;
52 ffd8a97f Hans de Goede
    int status, actual_length;
53 ffd8a97f Hans de Goede
    bool short_not_ok, done = false;
54 a552a966 Hans de Goede
55 a552a966 Hans de Goede
    if (combined == NULL) {
56 a552a966 Hans de Goede
        usb_packet_complete_one(dev, p);
57 a552a966 Hans de Goede
        goto leave;
58 a552a966 Hans de Goede
    }
59 a552a966 Hans de Goede
60 a552a966 Hans de Goede
    assert(combined->first == p && p == QTAILQ_FIRST(&combined->packets));
61 a552a966 Hans de Goede
62 9a77a0f5 Hans de Goede
    status = combined->first->status;
63 9a77a0f5 Hans de Goede
    actual_length = combined->first->actual_length;
64 a552a966 Hans de Goede
    short_not_ok = QTAILQ_LAST(&combined->packets, packets_head)->short_not_ok;
65 a552a966 Hans de Goede
66 a552a966 Hans de Goede
    QTAILQ_FOREACH_SAFE(p, &combined->packets, combined_entry, next) {
67 ffd8a97f Hans de Goede
        if (!done) {
68 a552a966 Hans de Goede
            /* Distribute data over uncombined packets */
69 9a77a0f5 Hans de Goede
            if (actual_length >= p->iov.size) {
70 9a77a0f5 Hans de Goede
                p->actual_length = p->iov.size;
71 a552a966 Hans de Goede
            } else {
72 a552a966 Hans de Goede
                /* Send short or error packet to complete the transfer */
73 9a77a0f5 Hans de Goede
                p->actual_length = actual_length;
74 ffd8a97f Hans de Goede
                done = true;
75 a552a966 Hans de Goede
            }
76 9a77a0f5 Hans de Goede
            /* Report status on the last packet */
77 ffd8a97f Hans de Goede
            if (done || next == NULL) {
78 9a77a0f5 Hans de Goede
                p->status = status;
79 9a77a0f5 Hans de Goede
            } else {
80 9a77a0f5 Hans de Goede
                p->status = USB_RET_SUCCESS;
81 9a77a0f5 Hans de Goede
            }
82 a552a966 Hans de Goede
            p->short_not_ok = short_not_ok;
83 ffd8a97f Hans de Goede
            /* Note will free combined when the last packet gets removed! */
84 a552a966 Hans de Goede
            usb_combined_packet_remove(combined, p);
85 a552a966 Hans de Goede
            usb_packet_complete_one(dev, p);
86 9a77a0f5 Hans de Goede
            actual_length -= p->actual_length;
87 a552a966 Hans de Goede
        } else {
88 a552a966 Hans de Goede
            /* Remove any leftover packets from the queue */
89 9a77a0f5 Hans de Goede
            p->status = USB_RET_REMOVE_FROM_QUEUE;
90 ffd8a97f Hans de Goede
            /* Note will free combined on the last packet! */
91 a552a966 Hans de Goede
            dev->port->ops->complete(dev->port, p);
92 a552a966 Hans de Goede
        }
93 a552a966 Hans de Goede
    }
94 ffd8a97f Hans de Goede
    /* Do not use combined here, it has been freed! */
95 a552a966 Hans de Goede
leave:
96 a552a966 Hans de Goede
    /* Check if there are packets in the queue waiting for our completion */
97 a552a966 Hans de Goede
    usb_ep_combine_input_packets(ep);
98 a552a966 Hans de Goede
}
99 a552a966 Hans de Goede
100 a552a966 Hans de Goede
/* May only be called for combined packets! */
101 a552a966 Hans de Goede
void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p)
102 a552a966 Hans de Goede
{
103 a552a966 Hans de Goede
    USBCombinedPacket *combined = p->combined;
104 a552a966 Hans de Goede
    assert(combined != NULL);
105 ffd8a97f Hans de Goede
    USBPacket *first = p->combined->first;
106 a552a966 Hans de Goede
107 ffd8a97f Hans de Goede
    /* Note will free combined on the last packet! */
108 a552a966 Hans de Goede
    usb_combined_packet_remove(combined, p);
109 ffd8a97f Hans de Goede
    if (p == first) {
110 a552a966 Hans de Goede
        usb_device_cancel_packet(dev, p);
111 a552a966 Hans de Goede
    }
112 a552a966 Hans de Goede
}
113 a552a966 Hans de Goede
114 a552a966 Hans de Goede
/*
115 a552a966 Hans de Goede
 * Large input transfers can get split into multiple input packets, this
116 a552a966 Hans de Goede
 * function recombines them, removing the short_not_ok checks which all but
117 a552a966 Hans de Goede
 * the last packet of such splits transfers have, thereby allowing input
118 a552a966 Hans de Goede
 * transfer pipelining (which we cannot do on short_not_ok transfers)
119 a552a966 Hans de Goede
 */
120 a552a966 Hans de Goede
void usb_ep_combine_input_packets(USBEndpoint *ep)
121 a552a966 Hans de Goede
{
122 a552a966 Hans de Goede
    USBPacket *p, *u, *next, *prev = NULL, *first = NULL;
123 a552a966 Hans de Goede
    USBPort *port = ep->dev->port;
124 9a77a0f5 Hans de Goede
    int totalsize;
125 a552a966 Hans de Goede
126 a552a966 Hans de Goede
    assert(ep->pipeline);
127 a552a966 Hans de Goede
    assert(ep->pid == USB_TOKEN_IN);
128 a552a966 Hans de Goede
129 a552a966 Hans de Goede
    QTAILQ_FOREACH_SAFE(p, &ep->queue, queue, next) {
130 a552a966 Hans de Goede
        /* Empty the queue on a halt */
131 a552a966 Hans de Goede
        if (ep->halted) {
132 9a77a0f5 Hans de Goede
            p->status = USB_RET_REMOVE_FROM_QUEUE;
133 a552a966 Hans de Goede
            port->ops->complete(port, p);
134 a552a966 Hans de Goede
            continue;
135 a552a966 Hans de Goede
        }
136 a552a966 Hans de Goede
137 a552a966 Hans de Goede
        /* Skip packets already submitted to the device */
138 a552a966 Hans de Goede
        if (p->state == USB_PACKET_ASYNC) {
139 a552a966 Hans de Goede
            prev = p;
140 a552a966 Hans de Goede
            continue;
141 a552a966 Hans de Goede
        }
142 a552a966 Hans de Goede
        usb_packet_check_state(p, USB_PACKET_QUEUED);
143 a552a966 Hans de Goede
144 a552a966 Hans de Goede
        /*
145 a552a966 Hans de Goede
         * If the previous (combined) packet has the short_not_ok flag set
146 a552a966 Hans de Goede
         * stop, as we must not submit packets to the device after a transfer
147 a552a966 Hans de Goede
         * ending with short_not_ok packet.
148 a552a966 Hans de Goede
         */
149 a552a966 Hans de Goede
        if (prev && prev->short_not_ok) {
150 a552a966 Hans de Goede
            break;
151 a552a966 Hans de Goede
        }
152 a552a966 Hans de Goede
153 a552a966 Hans de Goede
        if (first) {
154 a552a966 Hans de Goede
            if (first->combined == NULL) {
155 a552a966 Hans de Goede
                USBCombinedPacket *combined = g_new0(USBCombinedPacket, 1);
156 a552a966 Hans de Goede
157 a552a966 Hans de Goede
                combined->first = first;
158 a552a966 Hans de Goede
                QTAILQ_INIT(&combined->packets);
159 a552a966 Hans de Goede
                qemu_iovec_init(&combined->iov, 2);
160 a552a966 Hans de Goede
                usb_combined_packet_add(combined, first);
161 a552a966 Hans de Goede
            }
162 a552a966 Hans de Goede
            usb_combined_packet_add(first->combined, p);
163 a552a966 Hans de Goede
        } else {
164 a552a966 Hans de Goede
            first = p;
165 a552a966 Hans de Goede
        }
166 a552a966 Hans de Goede
167 a552a966 Hans de Goede
        /* Is this packet the last one of a (combined) transfer? */
168 579967be Hans de Goede
        totalsize = (p->combined) ? p->combined->iov.size : p->iov.size;
169 a552a966 Hans de Goede
        if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok ||
170 579967be Hans de Goede
                next == NULL ||
171 579967be Hans de Goede
                /* Work around for Linux usbfs bulk splitting + migration */
172 579967be Hans de Goede
                (totalsize == 16348 && p->int_req)) {
173 9a77a0f5 Hans de Goede
            usb_device_handle_data(ep->dev, first);
174 9a77a0f5 Hans de Goede
            assert(first->status == USB_RET_ASYNC);
175 a552a966 Hans de Goede
            if (first->combined) {
176 a552a966 Hans de Goede
                QTAILQ_FOREACH(u, &first->combined->packets, combined_entry) {
177 a552a966 Hans de Goede
                    usb_packet_set_state(u, USB_PACKET_ASYNC);
178 a552a966 Hans de Goede
                }
179 a552a966 Hans de Goede
            } else {
180 a552a966 Hans de Goede
                usb_packet_set_state(first, USB_PACKET_ASYNC);
181 a552a966 Hans de Goede
            }
182 a552a966 Hans de Goede
            first = NULL;
183 a552a966 Hans de Goede
            prev = p;
184 a552a966 Hans de Goede
        }
185 a552a966 Hans de Goede
    }
186 a552a966 Hans de Goede
}