From owner-freebsd-usb@FreeBSD.ORG Tue Jun 23 08:54:52 2009 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B8E0A1065673; Tue, 23 Jun 2009 08:54:52 +0000 (UTC) (envelope-from kosmo@semihalf.com) Received: from smtp.semihalf.com (smtp.semihalf.com [213.17.239.109]) by mx1.freebsd.org (Postfix) with ESMTP id 69A7E8FC1D; Tue, 23 Jun 2009 08:54:52 +0000 (UTC) (envelope-from kosmo@semihalf.com) Received: from [10.0.0.5] (cardhu.semihalf.com [213.17.239.108]) by smtp.semihalf.com (Postfix) with ESMTPSA id 63378C3BBC; Tue, 23 Jun 2009 10:34:14 +0200 (CEST) From: Piotr =?iso-8859-2?q?Zi=EAcik?= Organization: Semihalf To: Hans Petter Selasky Date: Tue, 23 Jun 2009 10:35:42 +0200 User-Agent: PLD Linux KMail/1.9.10 MIME-Version: 1.0 Content-Disposition: inline Message-Id: <200906231035.43096.kosmo@semihalf.com> X-UID: 355 Content-Type: text/plain; charset="iso-8859-2" Content-Transfer-Encoding: 7bit Cc: Rafal Jaworowski , thompsa@FreeBSD.org, freebsd-usb@freebsd.org Subject: CPU Cache and busdma usage in USB X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2009 08:54:53 -0000 While bringing up EHCI (8-CURRENT, new USB stack) on ARM machine we have found cache-related problem in the USB stack. The usb_pc_cpu_flush() and usb_pc_cpu_invalidate() functions are used to flush/invalidate CPU caches in various places in USB code. Internally, the functions are implemented using bus_dmamap_sync(). In our case, on ARM machine, flags passed to the bus_dmamap_sync() function did not correspond with requested operation. We have fixed the problem by changing flags passed to the bus_dmamap_sync() function (see attached patch). My question is about general idea of bus_dma usage for cache operations. In my opinion we should not rely on bus_dmamap_sync() behaviour as this function may do different things on different architectures. This not always works as expected, which is clearly visible in our case. Better solution is to use cpu-specific functions implementing cache operations. Please comment on why CPU-specific functions are not used... Patch fixing our problem: diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c index 3d6a5be..69a6fff 100644 --- a/sys/dev/usb/usb_busdma.c +++ b/sys/dev/usb/usb_busdma.c @@ -658,8 +658,7 @@ usb_pc_cpu_invalidate(struct usb_page_cache *pc) /* nothing has been loaded into this page cache! */ return; } - bus_dmamap_sync(pc->tag, pc->map, - BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD); } /*------------------------------------------------------------------------* @@ -672,8 +671,7 @@ usb_pc_cpu_flush(struct usb_page_cache *pc) /* nothing has been loaded into this page cache! */ return; } - bus_dmamap_sync(pc->tag, pc->map, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE); } /*------------------------------------------------------------------------* -- Best regards. Piotr Ziecik