From: Hans de Goede <hdegoede@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: Hans de Goede <hdegoede@redhat.com>, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] uhci: Use an intermediate buffer for usb packet data
Date: Mon, 6 May 2013 10:48:57 +0200 [thread overview]
Message-ID: <1367830137-9382-2-git-send-email-hdegoede@redhat.com> (raw)
In-Reply-To: <1367830137-9382-1-git-send-email-hdegoede@redhat.com>
Due to various unfortunate reasons we cannot reliable detect a guest
cancelling a packet as soon as it happens, instead we detect cancels
with some delay.
When packets are handled async, and we directly pass the guest memory for
the packet to the usb-device as iovec, this means that the usb-device can
write to guest-memory which the guest has already re-used for other purposes
-> not good!
This patch fixes this by adding an intermediate buffer and writing back not
only the result, but also the data, of async completed packets when scanning
the schedule.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb/hcd-uhci.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index f8c4286..c85b203 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -119,7 +119,8 @@ struct UHCIPCIDeviceClass {
struct UHCIAsync {
USBPacket packet;
- QEMUSGList sgl;
+ uint8_t static_buf[64]; /* 64 bytes is enough, except for isoc packets */
+ uint8_t *buf;
UHCIQueue *queue;
QTAILQ_ENTRY(UHCIAsync) next;
uint32_t td_addr;
@@ -264,7 +265,6 @@ static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t td_addr)
async->queue = queue;
async->td_addr = td_addr;
usb_packet_init(&async->packet);
- pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
trace_usb_uhci_packet_add(async->queue->token, async->td_addr);
return async;
@@ -274,7 +274,9 @@ static void uhci_async_free(UHCIAsync *async)
{
trace_usb_uhci_packet_del(async->queue->token, async->td_addr);
usb_packet_cleanup(&async->packet);
- qemu_sglist_destroy(&async->sgl);
+ if (async->buf != async->static_buf) {
+ g_free(async->buf);
+ }
g_free(async);
}
@@ -299,7 +301,6 @@ static void uhci_async_cancel(UHCIAsync *async)
async->done);
if (!async->done)
usb_cancel_packet(&async->packet);
- usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
}
@@ -774,6 +775,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
*int_mask |= 0x01;
if (pid == USB_TOKEN_IN) {
+ pci_dma_write(&s->dev, td->buffer, async->buf, len);
if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
*int_mask |= 0x02;
/* short packet: do not update QH */
@@ -881,12 +883,17 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0);
usb_packet_setup(&async->packet, pid, q->ep, 0, td_addr, spd,
(td->ctrl & TD_CTRL_IOC) != 0);
- qemu_sglist_add(&async->sgl, td->buffer, max_len);
- usb_packet_map(&async->packet, &async->sgl);
+ if (max_len <= sizeof(async->static_buf)) {
+ async->buf = async->static_buf;
+ } else {
+ async->buf = g_malloc(max_len);
+ }
+ usb_packet_addbuf(&async->packet, async->buf, max_len);
switch(pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
+ pci_dma_read(&s->dev, td->buffer, async->buf, max_len);
usb_handle_packet(q->ep->dev, &async->packet);
if (async->packet.status == USB_RET_SUCCESS) {
async->packet.actual_length = max_len;
@@ -899,7 +906,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
default:
/* invalid pid : frame interrupted */
- usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
s->status |= UHCI_STS_HCPERR;
uhci_update_irq(s);
@@ -916,7 +922,6 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
done:
ret = uhci_complete_td(s, td, async, int_mask);
- usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
return ret;
}
--
1.8.2.1
next prev parent reply other threads:[~2013-05-06 8:45 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-06 8:48 [Qemu-devel] [PATCH v2 0/1] uhci: Use an intermediate buffer for usb packet data Hans de Goede
2013-05-06 8:48 ` Hans de Goede [this message]
2013-05-07 13:36 ` [Qemu-devel] [PATCH] " Gerd Hoffmann
-- strict thread matches above, loose matches on Subject: below --
2013-04-25 10:21 Hans de Goede
2013-04-26 12:32 ` Gerd Hoffmann
2013-04-26 14:01 ` Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1367830137-9382-2-git-send-email-hdegoede@redhat.com \
--to=hdegoede@redhat.com \
--cc=kraxel@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).