From owner-freebsd-usb@FreeBSD.ORG Tue Feb 19 22:33:42 2013 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 0733F74C for ; Tue, 19 Feb 2013 22:33:42 +0000 (UTC) (envelope-from aman.sawrup@bluecoat.com) Received: from synonym.bluecoat.com (synonym.bluecoat.com [199.91.133.5]) by mx1.freebsd.org (Postfix) with ESMTP id D32C4C1E for ; Tue, 19 Feb 2013 22:33:41 +0000 (UTC) Received: from [10.167.0.106] (aman-sawrup.waterloo.bluecoat.com [10.167.0.106]) by synonym.bluecoat.com (Postfix) with ESMTP id 5527A7FE1B8; Tue, 19 Feb 2013 14:26:20 -0800 (PST) Message-ID: <5123FC0B.70009@bluecoat.com> Date: Tue, 19 Feb 2013 17:26:19 -0500 From: Aman Sawrup User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130106 Thunderbird/17.0.2 MIME-Version: 1.0 To: freebsd-usb@freebsd.org Subject: Insufficient memory reserved for xfer->dma_page_ptr? References: <1360360082956-5785167.post@n5.nabble.com> <201302090001.57258.hselasky@c2i.net> In-Reply-To: <201302090001.57258.hselasky@c2i.net> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Feb 2013 22:33:42 -0000 Hi Hans, I think I might have found a bug in usbd_transfer_setup_sub that causes insufficient memory allocated for xfer->dma_page_ptr. The code in question is: #if USB_HAVE_BUSDMA if (xfer->flags_int.bdma_enable) { /* * Setup "dma_page_ptr". * * Proof for formula below: * * Assume there are three USB frames having length "a", "b" and * "c". These USB frames will at maximum need "z" * "usb_page" structures. "z" is given by: * * z = ((a / USB_PAGE_SIZE) + 2) + ((b / USB_PAGE_SIZE) + 2) + * ((c / USB_PAGE_SIZE) + 2); * * Constraining "a", "b" and "c" like this: * * (a + b + c) <= parm->bufsize * * We know that: * * z <= ((parm->bufsize / USB_PAGE_SIZE) + (3*2)); * * Here is the general formula: */ xfer->dma_page_ptr = parm->dma_page_ptr; parm->dma_page_ptr += (2 * n_frbuffers); parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE); } #endif What I observe happening on a 64-bit x86 system is 4608 bytes reserved for xfer->dma_page_ptr. For example, this is what I see: (gdb) p parm->dma_page_ptr $75 = (struct usb_page *) 0x6dad46e0 (gdb) p xfer->dma_page_ptr $76 = (struct usb_page *) 0x6dad34e0 (gdb) p /d 0x6dad46e0 - 0x6dad34e0 $79 = 4608 (gdb) p /d sizeof(struct usb_page) $74 = 16 (gdb) p /d n_frbuffers $68 = 128 (gdb) p /d parm->bufsize $70 = 131072 I believe the amount of memory reserved needs to be much higher. For example, if sizeof(struct usb_page) is 16 bytes, then for n_frbuffers of 128 and parm->bufsize of 131072, we need the following amount of memory reserved: parm->bufsize / USB_PAGE_SIZE * n_frbuffers * sizeof(struct usb_page) = 131072 / 4096 * 128 * 16 = 65536 Thanks Aman