usb-ohci: td.cbp incorrectly updated near page end
authorAndriy Gapon <avg@FreeBSD.org>
Thu, 22 Dec 2011 09:34:30 +0000 (11:34 +0200)
committerJustin M. Forbes <jforbes@redhat.com>
Tue, 10 Jan 2012 15:45:48 +0000 (09:45 -0600)
The current code that updates the cbp value after a transfer looks like this:
td.cbp += ret;
if ((td.cbp & 0xfff) + ret > 0xfff) {
<handle page overflow>
because the 'ret' value is effectively added twice the check may fire too early
when the overflow hasn't happened yet.

Below is one of the possible changes that correct the behavior:

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
hw/usb-ohci.c

index c2981c59a4b828276974f22df6987ee8ce6d4a94..c27014a88f41b89bdc86554848893e760eb2b438 100644 (file)
@@ -1025,10 +1025,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
         if (ret == len) {
             td.cbp = 0;
         } else {
-            td.cbp += ret;
             if ((td.cbp & 0xfff) + ret > 0xfff) {
-                td.cbp &= 0xfff;
-                td.cbp |= td.be & ~0xfff;
+                td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
+            } else {
+                td.cbp += ret;
             }
         }
         td.flags |= OHCI_TD_T1;