From 7ac1b410ac9b66150170718a6f807ce52ffd8400 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 11 Jun 2014 16:03:34 -0600 Subject: dfu: allow backend to specify a maximum buffer size CONFIG_SYS_DFU_DATA_BUF_SIZE may be large to allow for FAT/ext layouts to transfer large files. However, this means that individual write operations will take a long time. Allow backends to specify a maximum buffer size, so that each write operation is limited to a smaller data block. This prevents the DFU protocol from timing out when e.g. writing to SPI flash. I would guess that NAND might benefit from setting this value too, but I can't test that. Signed-off-by: Stephen Warren diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 26d3b44..b8d382d 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -82,7 +82,7 @@ unsigned long dfu_get_buf_size(void) return dfu_buf_size; } -unsigned char *dfu_get_buf(void) +unsigned char *dfu_get_buf(struct dfu_entity *dfu) { char *s; @@ -92,6 +92,8 @@ unsigned char *dfu_get_buf(void) s = getenv("dfu_bufsiz"); dfu_buf_size = s ? (unsigned long)simple_strtol(s, NULL, 16) : CONFIG_SYS_DFU_DATA_BUF_SIZE; + if (dfu->max_buf_size && dfu_buf_size > dfu->max_buf_size) + dfu_buf_size = dfu->max_buf_size; dfu_buf = memalign(CONFIG_SYS_CACHELINE_SIZE, dfu_buf_size); if (dfu_buf == NULL) @@ -194,10 +196,10 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->offset = 0; dfu->bad_skip = 0; dfu->i_blk_seq_num = 0; - dfu->i_buf_start = dfu_get_buf(); + dfu->i_buf_start = dfu_get_buf(dfu); if (dfu->i_buf_start == NULL) return -ENOMEM; - dfu->i_buf_end = dfu_get_buf() + dfu_buf_size; + dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size; dfu->i_buf = dfu->i_buf_start; dfu->inited = 1; @@ -318,7 +320,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf); if (!dfu->inited) { - dfu->i_buf_start = dfu_get_buf(); + dfu->i_buf_start = dfu_get_buf(dfu); if (dfu->i_buf_start == NULL) return -ENOMEM; @@ -342,7 +344,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->i_blk_seq_num = 0; dfu->crc = 0; dfu->offset = 0; - dfu->i_buf_end = dfu_get_buf() + dfu_buf_size; + dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size; dfu->i_buf = dfu->i_buf_start; dfu->b_left = 0; @@ -398,6 +400,7 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, strcpy(dfu->name, st); dfu->alt = alt; + dfu->max_buf_size = 0; /* Specific for mmc device */ if (strcmp(interface, "mmc") == 0) { diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index 4e06273..c85b0fb 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -142,7 +142,8 @@ static long long int download_head(unsigned long long total, int *cnt) { long long int rcv_cnt = 0, left_to_rcv, ret_rcv; - void *transfer_buffer = dfu_get_buf(); + struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); + void *transfer_buffer = dfu_get_buf(dfu_entity); void *buf = transfer_buffer; int usb_pkt_cnt = 0, ret; @@ -205,7 +206,7 @@ static long long int download_head(unsigned long long total, static int download_tail(long long int left, int cnt) { struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); - void *transfer_buffer = dfu_get_buf(); + void *transfer_buffer = dfu_get_buf(dfu_entity); int ret; debug("%s: left: %llu cnt: %d\n", __func__, left, cnt); diff --git a/include/dfu.h b/include/dfu.h index 21390aa..d5562dc 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -91,6 +91,7 @@ struct dfu_entity { void *dev_private; enum dfu_device_type dev_type; enum dfu_layout layout; + unsigned long max_buf_size; union { struct mmc_internal_data mmc; @@ -138,7 +139,7 @@ void dfu_trigger_reset(void); int dfu_get_alt(char *name); bool dfu_reset(void); int dfu_init_env_entities(char *interface, char *devstr); -unsigned char *dfu_get_buf(void); +unsigned char *dfu_get_buf(struct dfu_entity *dfu); unsigned char *dfu_free_buf(void); unsigned long dfu_get_buf_size(void); -- cgit v0.10.2