From patchwork Thu Jan 28 16:46:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?=C5=81ukasz_Majewski?= X-Patchwork-Id: 574809 X-Patchwork-Delegate: l.majewski@samsung.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 78CA4140BF7 for ; Fri, 29 Jan 2016 03:47:35 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 08B01B37D9; Thu, 28 Jan 2016 17:47:29 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id FxLhfzYnCsFm; Thu, 28 Jan 2016 17:47:28 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6E07AA751B; Thu, 28 Jan 2016 17:47:28 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6ED8039B6 for ; Thu, 28 Jan 2016 17:47:11 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UU6ZGCcgbXcu for ; Thu, 28 Jan 2016 17:47:11 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by theia.denx.de (Postfix) with ESMTPS id 53E0C39C0 for ; Thu, 28 Jan 2016 17:46:58 +0100 (CET) Received: from epcpsbgm1new.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O1O00DJN9A3G4A0@mailout1.samsung.com> for u-boot@lists.denx.de; Fri, 29 Jan 2016 01:46:55 +0900 (KST) X-AuditID: cbfee61a-f79266d000003652-e4-56aa45ff9c22 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm1new.samsung.com (EPCPMTA) with SMTP id 28.FB.13906.FF54AA65; Fri, 29 Jan 2016 01:46:55 +0900 (KST) Received: from mcdsrvbld02.digital.local ([106.116.37.23]) by mmp2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O1O00AKL99T9J30@mmp2.samsung.com>; Fri, 29 Jan 2016 01:46:55 +0900 (KST) From: Lukasz Majewski To: u-boot@lists.denx.de, Tom Rini , Alex Gdalevich Date: Thu, 28 Jan 2016 17:46:36 +0100 Message-id: <1453999597-26991-2-git-send-email-l.majewski@samsung.com> X-Mailer: git-send-email 1.7.10.4 In-reply-to: <1453999597-26991-1-git-send-email-l.majewski@samsung.com> References: <1453999597-26991-1-git-send-email-l.majewski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrILMWRmVeSWpSXmKPExsVy+t9jQd3/rqvCDDqPcVkcmT+fzeLhVX+L HXfuM1u8ecRt8ebhZkaLN22NjBa3Pm9gtdhx+QaLxYG571ksXh1sY7GYOmkzu8WFU7uZLN7u 7WR34PVomnyZxWPerBMsHjtn3WX3eHVgFbvH2Ts7GD3WTXvL7NHb/I7No6G/h9Gjb8sqRo/t JycxeWycGxrAHcVlk5Kak1mWWqRvl8CVsf9jO3vBVN2Kh8eusTUw/lLuYuTgkBAwkXi/O7OL kRPIFJO4cG89WxcjF4eQwCxGifUr97BAOH8YJY7fmM8IUsUmoCfx+e5TJhBbRCBb4v+aW2Ad zAJ9zBK9U9aygiSEBQIkvlz+AdbAIqAq0feulw3E5hVwk5jWsJwZYp2iRPezCWBxTgF3iT33 JrGA2EJANWfO7maewMi7gJFhFaNEakFyQXFSeq5hXmq5XnFibnFpXrpecn7uJkZwQD+T2sF4 cJf7IUYBDkYlHl7GqJVhQqyJZcWVuYcYJTiYlUR4Z1utChPiTUmsrEotyo8vKs1JLT7EKM3B oiTOW3spMkxIID2xJDU7NbUgtQgmy8TBKdXAKHFsO9OTe4791pFveu9+6JgRsCz2pnZx3MYT fVM+1LVJXUlepsv8iTuNT9an5Ox0Hrcrf1RWsj7IOSa22THt1fxT944uT3uxXql5X8udpM0/ NE88jvk2PXrpA62ch2Vt51lez5mn6WpyVF5pFn9GBNezJTGmBS73Uh5M7uG+7fTyVOefHZ4/ FyqxFGckGmoxFxUnAgDb79w4ZAIAAA== Cc: Marek Vasut , Otavio Salvador , Samuel Egli , Przemyslaw Marczak , Tom Warren Subject: [U-Boot] [PATCH 1/2] dfu: usb: f_dfu: Set deferred call for dfu_flush() function X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch fixes situation when one would like to write large file into medium with the file system (fat, ext4, etc). This change sets file size limitation to the DFU internal buffer size. Since u-boot is not supporting interrupts and seek on file systems, it becomes challenging to store large file appropriately. To reproduce this error - create large file (around 26 MiB) and sent it to the target board. Lets examine the flow of USB transactions: 0. DFU uses EP0 with 64B MPS [Max Packet Size] 1. Send file - OUT (PC->target) - dat_26MiB.img is sent with 4096 B transactions 2. Get status - OUT (PC->target) - wait for DFU_STATE_dfuDNLOAD_IDLE (0x05) sent from target board - IN transaction (target->PC) 3. The whole file content is sent to target - OUT (PC->target) with ZLP [Zero Length Packet] Now the interesting part starts: 4. OUT (PC->target) Setup transaction (request to share DFU state) 5. IN (target->PC) - reply the current DFU state - In the UDC driver the req->completion (with dfu_flush) is called after successful IN transfer. - The dfu_flush() (called from req->completion callback) saves the whole file at once (u-boot doesn't support seek on fs). Such operation takes considerable time. When the file is large - e.g. 26MiB - this time may be more than 5 seconds. 6. OUT (PC->target) - ZLP, is send in the same time when dfu_flush() writes data to eMMC memory. The dfu-util application has hard coded timeout on USB transaction completion set to 5 seconds (it uses libusb calls). When the file to store is large (e.g. 26 MiB) the time needed to write it may excess the dfu-util timeout and following error message will be displayed: "unable to read DFU status" on the HOST PC console. This change is supposed to leverage DFU's part responsible for storing files on file systems. Other DFU operations - i.e. raw/partition write to NAND and eMMC should work as before. The only functional change is the error reporting. When dfu_flush() fails the u-boot prompt will exit with error information and dfu-util application exits afterwards as well. Test HW: - Odroid XU3 (Exynos5433) - test with large file - Trats (Exynos4210) - test for regression - eMMC, raw, Signed-off-by: Lukasz Majewski Reported-by: Alex Gdalevich Tested-by: Stephen Warren Tested-by: Heiko Schocher --- common/cmd_dfu.c | 20 ++++++++++++++++++++ drivers/usb/gadget/f_dfu.c | 11 +++-------- include/dfu.h | 25 +++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c index 6d95ce9..d8aae26 100644 --- a/common/cmd_dfu.c +++ b/common/cmd_dfu.c @@ -79,6 +79,26 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (ctrlc()) goto exit; + if (dfu_get_defer_flush()) { + /* + * Call to usb_gadget_handle_interrupts() is necessary + * to act on ZLP OUT transaction from HOST PC after + * transmitting the whole file. + * + * If this ZLP OUT packet is NAK'ed, the HOST libusb + * function fails after timeout (by default it is set to + * 5 seconds). In such situation the dfu-util program + * exits with error message. + */ + usb_gadget_handle_interrupts(controller_index); + ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0); + dfu_set_defer_flush(NULL); + if (ret) { + error("Deferred dfu_flush() failed!"); + goto exit; + } + } + WATCHDOG_RESET(); usb_gadget_handle_interrupts(controller_index); } diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 77a1567..7d88008 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -44,6 +44,8 @@ struct f_dfu { unsigned int poll_timeout; }; +struct dfu_entity *dfu_defer_flush; + typedef int (*dfu_state_fn) (struct f_dfu *, const struct usb_ctrlrequest *, struct usb_gadget *, @@ -167,14 +169,7 @@ static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req) { struct f_dfu *f_dfu = req->context; - int ret; - - ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf, - req->length, f_dfu->blk_seq_num); - if (ret) { - f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; - f_dfu->dfu_state = DFU_STATE_dfuERROR; - } + dfu_set_defer_flush(dfu_get_entity(f_dfu->altsetting)); } static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu) diff --git a/include/dfu.h b/include/dfu.h index 6118dc2..f39d3f1 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -163,6 +163,31 @@ int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num); int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num); int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num); +/* + * dfu_defer_flush - pointer to store dfu_entity for deferred flashing. + * It should be NULL when not used. + */ +extern struct dfu_entity *dfu_defer_flush; +/** + * dfu_get_defer_flush - get current value of dfu_defer_flush pointer + * + * @return - value of the dfu_defer_flush pointer + */ +static inline struct dfu_entity *dfu_get_defer_flush(void) +{ + return dfu_defer_flush; +} + +/** + * dfu_set_defer_flush - set the dfu_defer_flush pointer + * + * @param dfu - pointer to the dfu_entity, which should be written + */ +static inline void dfu_set_defer_flush(struct dfu_entity *dfu) +{ + dfu_defer_flush = dfu; +} + /** * dfu_write_from_mem_addr - write data from memory to DFU managed medium *