From owner-p4-projects@FreeBSD.ORG Sun Jan 13 11:45:53 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id AFBE116A421; Sun, 13 Jan 2008 11:45:53 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 74D1916A417 for ; Sun, 13 Jan 2008 11:45:53 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 7494013C459 for ; Sun, 13 Jan 2008 11:45:53 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m0DBjrMe077776 for ; Sun, 13 Jan 2008 11:45:53 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m0DBjra3077773 for perforce@freebsd.org; Sun, 13 Jan 2008 11:45:53 GMT (envelope-from hselasky@FreeBSD.org) Date: Sun, 13 Jan 2008 11:45:53 GMT Message-Id: <200801131145.m0DBjra3077773@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 133182 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 13 Jan 2008 11:45:54 -0000 http://perforce.freebsd.org/chv.cgi?CH=133182 Change 133182 by hselasky@hselasky_laptop001 on 2008/01/13 11:44:56 OHCI isochronous "off by one" bugfix. When doing isochronous transfers the final physical page was computed like: usbd_get_page(xfer->frbuffers + 0, buf_offset, &buf_res); Instead of: usbd_get_page(xfer->frbuffers + 0, buf_offset-1, &buf_res); This can lead to invalid memory access in some special cases. Non-isochronous transfers are not affected. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/ohci.c#57 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/ohci.c#57 (text+ko) ==== @@ -1907,24 +1907,22 @@ struct ohci_hcca *hcca; uint32_t buf_offset; uint32_t nframes; - uint32_t bp0; - uint32_t end_phy; uint32_t ed_flags; uint32_t *plen; uint16_t itd_offset[OHCI_ITD_NOFFSET]; + uint16_t length; uint8_t ncur; - uint8_t allzero = 1; ohci_itd_t *td; ohci_itd_t *td_last = NULL; ohci_ed_t *ed; - DPRINTFN(5, ("xfer=%p next=%d nframes=%d\n", - xfer, xfer->pipe->isoc_next, xfer->nframes)); - hcca = ohci_get_hcca(sc); nframes = le32toh(hcca->hcca_frame_number); + DPRINTFN(5, ("xfer=%p isoc_next=%u nframes=%u hcca_fn=%u\n", + xfer, xfer->pipe->isoc_next, xfer->nframes, nframes)); + if ((LIST_FIRST(&(xfer->pipe->list_head)) == NULL) || (((nframes - xfer->pipe->isoc_next) & 0xFFFF) < xfer->nframes) || (((xfer->pipe->isoc_next - nframes) & 0xFFFF) >= 128)) { @@ -1955,7 +1953,6 @@ nframes = xfer->nframes; buf_offset = 0; - usbd_get_page(xfer->frbuffers + 0, buf_offset, &buf_res); plen = xfer->frlengths; @@ -1968,32 +1965,24 @@ xfer->td_transfer_first = td; ncur = 0; - - bp0 = OHCI_PAGE(buf_res.physaddr); + length = 0; - end_phy = 0; - while (nframes--) { if (td == NULL) { panic("%s:%d: out of TD's\n", __FUNCTION__, __LINE__); } - itd_offset[ncur] = htole16(OHCI_ITD_MK_OFFS - (buf_res.physaddr - bp0)); - if (*plen) { - allzero = 0; - buf_offset += (*plen) - 1; - usbd_get_page(xfer->frbuffers + 0, buf_offset, &buf_res); - - end_phy = buf_res.physaddr; - buf_offset += 1; - usbd_get_page(xfer->frbuffers + 0, buf_offset, &buf_res); - } + itd_offset[ncur] = length; + buf_offset += *plen; + length += *plen; plen++; ncur++; - if ((ncur == OHCI_ITD_NOFFSET) || - (OHCI_PAGE(buf_res.physaddr) != bp0) || + if (/* check if the ITD is full */ + (ncur == OHCI_ITD_NOFFSET) || + /* check if we have put more than 4K into the ITD */ + (length & 0xF000) || + /* check if it is the last frame */ (nframes == 0)) { /* fill current ITD */ @@ -2003,22 +1992,37 @@ OHCI_ITD_NOINTR | OHCI_ITD_SET_FC(ncur)); - if (allzero) { + td->frames = ncur; + xfer->pipe->isoc_next += ncur; + + if (length == 0) { + /* all zero */ td->itd_bp0 = 0; td->itd_be = ~0; + + while (ncur--) { + td->itd_offset[ncur] = + htole16(OHCI_ITD_MK_OFFS(0)); + } } else { - td->itd_bp0 = htole32(bp0); - td->itd_be = htole32(end_phy); - } - td->frames = ncur; + usbd_get_page(xfer->frbuffers + 0, buf_offset-length, &buf_res); + length = OHCI_PAGE_MASK(buf_res.physaddr); + buf_res.physaddr = + OHCI_PAGE(buf_res.physaddr); + td->itd_bp0 = htole32(buf_res.physaddr); + usbd_get_page(xfer->frbuffers + 0, buf_offset-1, &buf_res); + td->itd_be = htole32(buf_res.physaddr); - xfer->pipe->isoc_next += ncur; - bp0 = OHCI_PAGE(buf_res.physaddr); - while (ncur--) { - td->itd_offset[ncur] = itd_offset[ncur]; + while (ncur--) { + itd_offset[ncur] += length; + itd_offset[ncur] = + OHCI_ITD_MK_OFFS(itd_offset[ncur]); + td->itd_offset[ncur] = + htole16(itd_offset[ncur]); + } } ncur = 0; - allzero = 1; + length = 0; td_last = td; td = td->obj_next;