I fixed a serious DMA physical address translation bug in OHCI today.
   Look on the lists today for this message.  Message and patch enclosed.

   Note that this fixes one bug in FreeBSD's implementation and a second
   bug that is NetBSD/OpenBSD specific.  I would appreciate it if someone
   would forward this information to the NetBSD/OpenBSD folks.

   These were very serious bugs.

                                                -Matt

:Date: Thu, 19 Dec 2002 17:11:32 -0800 (PST)
:From: Matthew Dillon <[EMAIL PROTECTED]>
:Message-Id: <[EMAIL PROTECTED]>
:To: Nate Lawson <[EMAIL PROTECTED]>
:Cc: [EMAIL PROTECTED]
:Subject: Re: UMASS USB bug? (getting the Sony disk-on-key device working)
:References:  <[EMAIL PROTECTED]>
:Sender: [EMAIL PROTECTED]
:List-ID: <freebsd-current.FreeBSD.ORG>
:List-Archive: <http://docs.freebsd.org/mail/> (Web Archive)
:List-Help: <mailto:[EMAIL PROTECTED]?subject=help> (List Instructions)
:List-Subscribe: <mailto:[EMAIL PROTECTED]?subject=subscribe%20freebsd-current>
:List-Unsubscribe: <mailto:[EMAIL PROTECTED]?subject=unsubscribe%20freebsd-current>
:X-Loop: FreeBSD.ORG
:Precedence: bulk
:...
:

Index: ohci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ohci.c,v
retrieving revision 1.116
diff -u -r1.116 ohci.c
--- ohci.c      9 Dec 2002 01:41:24 -0000       1.116
+++ ohci.c      20 Dec 2002 01:02:11 -0000
@@ -493,17 +493,17 @@
        u_int32_t intr, tdflags;
        int offset = 0;
        int len, curlen;
+       int orig_len;
        usb_dma_t *dma = &xfer->dmabuf;
        u_int16_t flags = xfer->flags;
 
        DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
 
-       len = alen;
+       orig_len = len = alen;
        cur = sp;
 
-
        dataphys = DMAADDR(dma, 0);
-       dataphysend = OHCI_PAGE(dataphys + len - 1);
+       dataphysend = OHCI_PAGE(DMAADDR(dma, len - 1));
        tdflags = htole32(
            (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
            (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
@@ -518,8 +518,8 @@
 
                /* The OHCI hardware can handle at most one page crossing. */
 #if defined(__NetBSD__) || defined(__OpenBSD__)
-               if (OHCI_PAGE(dataphys) == OHCI_PAGE(dataphysend) ||
-                   OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == OHCI_PAGE(dataphysend))
+               if (OHCI_PAGE(dataphys) == dataphysend ||
+                   OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend)
 #elif defined(__FreeBSD__)
                /* XXX This is pretty broken: Because we do not allocate
                 * a contiguous buffer (contiguous in physical pages) we
@@ -527,7 +527,7 @@
                 * So check whether the start and end of the buffer are on
                 * the same page.
                 */
-               if (OHCI_PAGE(dataphys) == OHCI_PAGE(dataphysend))
+               if (OHCI_PAGE(dataphys) == dataphysend)
 #endif
                {
                        /* we can handle it in this TD */
@@ -544,6 +544,8 @@
                        /* must use multiple TDs, fill as much as possible. */
                        curlen = 2 * OHCI_PAGE_SIZE -
                                 OHCI_PAGE_MASK(dataphys);
+                       if (curlen > len)       /* may have fit in one page */
+                               curlen = len;
 #elif defined(__FreeBSD__)
                        /* See comment above (XXX) */
                        curlen = OHCI_PAGE_SIZE -
@@ -568,6 +570,9 @@
                            dataphys, dataphys + curlen - 1));
                if (len == 0)
                        break;
+               if (len < 0)
+                       panic("Length went negative: %d curlen %d (dma %p offset %08x 
+dataphysend %p currentdataphysend %p", len, curlen, *dma, (int)offset, (void 
+*)dataphysend, (void *)OHCI_PAGE(DMAADDR(dma,0) + orig_len - 1));
+
                DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
                offset += curlen;
                cur = next;

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to