diff mbox

[U-Boot,2/4] usb: dfu: f_dfu: Provide infrastructure to adjust DFU's Poll Timeout value

Message ID 1386602416-12863-3-git-send-email-l.majewski@samsung.com
State Accepted
Delegated to: Marek Vasut
Headers show

Commit Message

Łukasz Majewski Dec. 9, 2013, 3:20 p.m. UTC
It is necessary to deter the host from sending subsequent DFU_GETSTATUS
request in the case of e.g. writing the buffer to medium.

Here the timeout is increased when we fill up the whole buffer. This delay
allows eMMC memory to perform its internal operations.
Otherwise we end up with HOST's error regarding GET_STATUS receive timeout.
	
Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
---
 drivers/usb/gadget/f_dfu.c |   39 ++++++++++++++++++++++++++++++++++++---
 drivers/usb/gadget/f_dfu.h |    2 ++
 include/dfu.h              |    3 +++
 3 files changed, 41 insertions(+), 3 deletions(-)

Comments

Bo Shen Dec. 10, 2013, 6:34 a.m. UTC | #1
Hi Lukasz,

On 12/09/2013 11:20 PM, Lukasz Majewski wrote:
> diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
> index cc2c455..0c29954 100644
> --- a/drivers/usb/gadget/f_dfu.h
> +++ b/drivers/usb/gadget/f_dfu.h
> @@ -82,4 +82,6 @@ struct dfu_function_descriptor {
>   	__le16				wTransferSize;
>   	__le16				bcdDFUVersion;
>   } __packed;
> +
> +#define DFU_POLL_TIMEOUT_MASK           (0xFFFFFFUL)

Why this value? How about (~0UL)?

>   #endif /* __F_DFU_H_ */

Best Regards,
Bo Shen
Łukasz Majewski Dec. 10, 2013, 8:27 a.m. UTC | #2
Hi Bo,

> Hi Lukasz,
> 
> On 12/09/2013 11:20 PM, Lukasz Majewski wrote:
> > diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
> > index cc2c455..0c29954 100644
> > --- a/drivers/usb/gadget/f_dfu.h
> > +++ b/drivers/usb/gadget/f_dfu.h
> > @@ -82,4 +82,6 @@ struct dfu_function_descriptor {
> >   	__le16				wTransferSize;
> >   	__le16				bcdDFUVersion;
> >   } __packed;
> > +
> > +#define DFU_POLL_TIMEOUT_MASK           (0xFFFFFFUL)
> 
> Why this value? How about (~0UL)?

According to DFU 1.1 standard, the bwPolTimeout field of DFU_GETSTATUS
request has 3 bytes in size.

> 
> >   #endif /* __F_DFU_H_ */
> 
> Best Regards,
> Bo Shen
Bo Shen Dec. 10, 2013, 8:37 a.m. UTC | #3
Hi Lukasz,

On 12/10/2013 04:27 PM, Lukasz Majewski wrote:
> Hi Bo,
>
>> Hi Lukasz,
>>
>> On 12/09/2013 11:20 PM, Lukasz Majewski wrote:
>>> diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
>>> index cc2c455..0c29954 100644
>>> --- a/drivers/usb/gadget/f_dfu.h
>>> +++ b/drivers/usb/gadget/f_dfu.h
>>> @@ -82,4 +82,6 @@ struct dfu_function_descriptor {
>>>    	__le16				wTransferSize;
>>>    	__le16				bcdDFUVersion;
>>>    } __packed;
>>> +
>>> +#define DFU_POLL_TIMEOUT_MASK           (0xFFFFFFUL)
>>
>> Why this value? How about (~0UL)?
>
> According to DFU 1.1 standard, the bwPolTimeout field of DFU_GETSTATUS
> request has 3 bytes in size.

Thanks for clarify this.

Tested OK on sama5d3xek board.
Tested-by: Bo Shen <voice.shen@atmel.com>

>>
>>>    #endif /* __F_DFU_H_ */
>>
>> Best Regards,
>> Bo Shen
>

Best Regards,
Bo Shen
Heiko Schocher Dec. 10, 2013, 10:49 a.m. UTC | #4
Hello Lukasz,

Am 09.12.2013 16:20, schrieb Lukasz Majewski:
> It is necessary to deter the host from sending subsequent DFU_GETSTATUS
> request in the case of e.g. writing the buffer to medium.
>
> Here the timeout is increased when we fill up the whole buffer. This delay
> allows eMMC memory to perform its internal operations.
> Otherwise we end up with HOST's error regarding GET_STATUS receive timeout.
> 	
> Signed-off-by: Lukasz Majewski<l.majewski@samsung.com>
> ---
>   drivers/usb/gadget/f_dfu.c |   39 ++++++++++++++++++++++++++++++++++++---
>   drivers/usb/gadget/f_dfu.h |    2 ++
>   include/dfu.h              |    3 +++
>   3 files changed, 41 insertions(+), 3 deletions(-)

Tested on the dxr2 board. "dfu -l" "dfu -U" and "dfu -D" worked.

Tested-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
diff mbox

Patch

diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 37d04a1..b4b4aa4 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -40,6 +40,7 @@  struct f_dfu {
 
 	/* Send/received block number is handy for data integrity check */
 	int                             blk_seq_num;
+	unsigned int                    poll_timeout;
 };
 
 typedef int (*dfu_state_fn) (struct f_dfu *,
@@ -128,6 +129,33 @@  static struct usb_gadget_strings *dfu_strings[] = {
 	NULL,
 };
 
+static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms)
+{
+	/*
+	 * The bwPollTimeout DFU_GETSTATUS request payload provides information
+	 * about minimum time, in milliseconds, that the host should wait before
+	 * sending a subsequent DFU_GETSTATUS request
+	 *
+	 * This permits the device to vary the delay depending on its need to
+	 * erase or program the memory
+	 *
+	 */
+
+	unsigned char *p = (unsigned char *)&ms;
+
+	if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) {
+		dstat->bwPollTimeout[0] = 0;
+		dstat->bwPollTimeout[1] = 0;
+		dstat->bwPollTimeout[2] = 0;
+
+		return;
+	}
+
+	dstat->bwPollTimeout[0] = *p++;
+	dstat->bwPollTimeout[1] = *p++;
+	dstat->bwPollTimeout[2] = *p;
+}
+
 /*-------------------------------------------------------------------------*/
 
 static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
@@ -157,11 +185,15 @@  static void handle_getstatus(struct usb_request *req)
 		break;
 	}
 
+	dfu_set_poll_timeout(dstat, 0);
+
+	if (f_dfu->poll_timeout)
+		if (!(f_dfu->blk_seq_num %
+		      (dfu_get_buf_size() / DFU_USB_BUFSIZ)))
+			dfu_set_poll_timeout(dstat, f_dfu->poll_timeout);
+
 	/* send status response */
 	dstat->bStatus = f_dfu->dfu_status;
-	dstat->bwPollTimeout[0] = 0;
-	dstat->bwPollTimeout[1] = 0;
-	dstat->bwPollTimeout[2] = 0;
 	dstat->bState = f_dfu->dfu_state;
 	dstat->iString = 0;
 }
@@ -725,6 +757,7 @@  static int dfu_bind_config(struct usb_configuration *c)
 	f_dfu->usb_function.disable = dfu_disable;
 	f_dfu->usb_function.strings = dfu_generic_strings,
 	f_dfu->usb_function.setup = dfu_handle,
+	f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT;
 
 	status = usb_add_function(c, &f_dfu->usb_function);
 	if (status)
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
index cc2c455..0c29954 100644
--- a/drivers/usb/gadget/f_dfu.h
+++ b/drivers/usb/gadget/f_dfu.h
@@ -82,4 +82,6 @@  struct dfu_function_descriptor {
 	__le16				wTransferSize;
 	__le16				bcdDFUVersion;
 } __packed;
+
+#define DFU_POLL_TIMEOUT_MASK           (0xFFFFFFUL)
 #endif /* __F_DFU_H_ */
diff --git a/include/dfu.h b/include/dfu.h
index 9a50721..f973426 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -77,6 +77,9 @@  static inline unsigned int get_mmc_blk_size(int dev)
 #ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
 #define CONFIG_SYS_DFU_MAX_FILE_SIZE CONFIG_SYS_DFU_DATA_BUF_SIZE
 #endif
+#ifndef DFU_DEFAULT_POLL_TIMEOUT
+#define DFU_DEFAULT_POLL_TIMEOUT 0
+#endif
 
 struct dfu_entity {
 	char			name[DFU_NAME_SIZE];