common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks
PATCH v2 1/1 common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks
Implements the logic to calculate the optimal usb maximum trasfer blocks instead of sending USB_MAX_XFER_BLK blocks which is 65535 and 20 in case of EHCI and other USB protocols respectively.
It defines USB_MIN_XFER_BLK/USB_MAX_XFER_BLK trasfer blocks that should be checked for success starting from minimum to maximum, and rest of the read/write are performed with that optimal value. It tries to increase/ decrease the blocks in follwing scenarios:
1.decrease blocks: when read/write for a particular number of blocks fails.
2. increase blocks: when read/write for a particular number of blocks pass and amount left to trasfer is greater than current number of blocks.
Currently changes are done for EHCI where min = 4096 and max = 65535 is taken. And for other cases code is left unchanged by keeping min = max = 20.
--- common/usb_storage.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-)
common/usb_storage.c +59 -12
@@ -106,10 +106,13 @@ struct us_data {* enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are * limited to 65535 blocks. */ +#define USB_MIN_XFER_BLK 4095#define USB_MAX_XFER_BLK 65535#else +#define USB_MIN_XFER_BLK 20#define USB_MAX_XFER_BLK 20#endif +#define USB_CUR_XFER_BLK (n) (n >= 0 ? ((1 << (12 + (n))) - 1) : 0)#ifndef CONFIG_BLK static struct us_data usb_stor[USB_MAX_STOR_DEV ];
@@ -1117,11 +1120,13 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);if (blkcnt ==0 )return 0 ;
@@ -1153,26 +1158,46 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,/* XXX need some comment here */ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_read: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_read_10 (srb, ss, start, smallblks)) {debug ("Read ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size; + usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it; + } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;
@@ -1181,7 +1206,7 @@ retry_it: start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt; }
@@ -1199,11 +1224,13 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);if (blkcnt ==0 )return 0 ;
@@ -1239,26 +1266,46 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,*/ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_write: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_write_10 (srb, ss, start, smallblks)) {debug ("Write ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size; + usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it; + } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;
@@ -1266,7 +1313,7 @@ retry_it: PRIxPTR "\n", start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt;
Signature · 1 line
2.6.2.198.g614a2ac
PATCH v2 1/1 common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks
Quoted 30 lines · Rajesh Bhagat
Implements the logic to calculate the optimal usb maximum trasfer blocks instead of sending
USB_MAX_XFER_BLKblocks which is 65535 and 20 in case of EHCI and other USB protocols respectively.It defines USB_MIN_XFER_BLK/USB_MAX_XFER_BLK trasfer blocks that should be checked for success starting from minimum to maximum, and rest of the read/write are performed with that optimal value. It tries to increase/ decrease the blocks in follwing scenarios:
1.decrease blocks: when read/write for a particular number of blocks fails.
2. increase blocks: when read/write for a particular number of blocks pass and amount left to trasfer is greater than current number of blocks.Currently changes are done for EHCI where min = 4096 and max = 65535 is taken. And for other cases code is left unchanged by keeping min = max = 20.
Signed-off-by Sriram Dash <[email protected]>Signed-off-by Rajesh Bhagat <[email protected]>--- common/usb_storage.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-)common/usb_storage.c +0
-0
common/usb_storage.c struct us_data { · line 115
Quoted 10 lines
common/usb_storage.c +3
-0@@ -106,10 +106,13 @@ struct us_data {* enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are * limited to 65535 blocks. */ +#define USB_MIN_XFER_BLK 4095#define USB_MAX_XFER_BLK 65535#else +#define USB_MIN_XFER_BLK 20#define USB_MAX_XFER_BLK 20#endif +#define USB_CUR_XFER_BLK (n) (n >= 0 ? ((1 << (12 + (n))) - 1) : 0)
Can this be ever called with n < 0 ? You should make this into a function to get typechecking on it too.
Quoted 4 lines
common/usb_storage.c +0
-0#ifndef CONFIG_BLK static struct us_data usb_stor[USB_MAX_STOR_DEV ];@@ -1117,11 +1120,13 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,unsigned short smallblks;
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, · line 1129
Quoted 10 lines
common/usb_storage.c +3
-1struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);
How will this behave if you keep alternating between two block_dev devices ? It will always start looking for the best possible transfer length from scratch, right ? That's not great ...
Quoted 24 lines
common/usb_storage.c +5
-4if (blkcnt ==0 )return 0 ;@@ -1153,26 +1158,46 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,/* XXX need some comment here */ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_read: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_read_10 (srb, ss, start, smallblks)) {debug ("Read ERROR\n" );usb_request_sense (srb, ss); -if (retry--)
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, · line 1184
Quoted 10 lines
common/usb_storage.c +9
-0+if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size; + usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it;
What is the reason for having the same code twice in this patch ? Just pull the identical stuff into a function.
Quoted 104 lines
common/usb_storage.c +39
-7+ } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;@@ -1181,7 +1206,7 @@ retry_it: start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt; }@@ -1199,11 +1224,13 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);if (blkcnt ==0 )return 0 ;@@ -1239,26 +1266,46 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,*/ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_write: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_write_10 (srb, ss, start, smallblks)) {debug ("Write ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size; + usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it; + } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;@@ -1266,7 +1313,7 @@ retry_it: PRIxPTR "\n", start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt;
Signature · 2 lines
Best regards, Marek Vasut
PATCH v2 1/1 common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks
Quoted 45 lines
-----Original Message-----
From: Marek Vasut [mailto:marex at denx.de]
Sent: Saturday, June 04, 2016 4:22 AM
To: Rajesh Bhagat <[email protected]>; u-boot at lists.denx.de
Cc: sjg at chromium.org; york sun <[email protected]>; Sriram Dash <[email protected]>
Subject: Re: [PATCH v2] common:usb_storage: Implement logic to calculate optimal usb maximum trasfer blocksQuoted 31 lines · Rajesh Bhagat
Implements the logic to calculate the optimal usb maximum trasfer blocks instead of sending
USB_MAX_XFER_BLKblocks which is 65535 and 20 in case of EHCI and other USB protocols respectively.It defines USB_MIN_XFER_BLK/USB_MAX_XFER_BLK trasfer blocks that should be checked for success starting from minimum to maximum, and rest of the read/write are performed with that optimal value. It tries to increase/ decrease the blocks in follwing scenarios:
1.decrease blocks: when read/write for a particular number of blocks fails.
2. increase blocks: when read/write for a particular number of blocks pass and amount left to trasfer is greater than current number of blocks.Currently changes are done for EHCI where min = 4096 and max = 65535 is taken. And for other cases code is left unchanged by keeping min = max = 20.
Signed-off-by Sriram Dash <[email protected]>Signed-off-by Rajesh Bhagat <[email protected]>--- common/usb_storage.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-)common/usb_storage.c index renamed from common/usb_storage.c +0
-07e6e52d..eee8f4c 100644
common/usb_storage.c struct us_data { · line 106
Quoted 1 line
common/usb_storage.c +0
-0@@ -106,10 +106,13 @@ struct us_data {* enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
Quoted 10 lines
common/usb_storage.c struct us_data { · line 115
Quoted 9 lines
common/usb_storage.c +3
-0* limited to 65535 blocks. */ +#define USB_MIN_XFER_BLK 4095#define USB_MAX_XFER_BLK 65535#else +#define USB_MIN_XFER_BLK 20#define USB_MAX_XFER_BLK 20#endif +#define USB_CUR_XFER_BLK (n) (n >= 0 ? ((1 << (12 + (n))) - 1) : 0)
Hello Marek,
Quoted 3 lines
Can this be ever called with n < 0 ? You should make this into a function to get typechecking on it too.
Yes. When transfer fails for the first time (pos - 1) is passed to this macro. Ok, I will convert it to a function in v3.
Quoted 4 lines
common/usb_storage.c struct us_data { · line 118
Quoted 3 lines
common/usb_storage.c +1
-0#ifndef CONFIG_BLK static struct us_data usb_stor[USB_MAX_STOR_DEV]; @@ -1117,11 +1120,13 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev,
lbaint_tblknr,
Quoted 15 lines
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, · line 1129
Quoted 11 lines
common/usb_storage.c +3
-1unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);How will this behave if you keep alternating between two
block_devdevices ? It will always start looking for the best possible transfer length from scratch, right ? That's not great ...
How about adding a field name "cur_xfer_blks" in struct usb_device and updating it on device basis , it will help retain the value.
struct usb_device {
...
unsigned short cur_xfer_blks; };
Quoted 31 lines
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc
Quoted 4 lines
common/usb_storage.c +0
-0if (blkcnt ==0 )return 0 ;@@ -1153,26 +1158,46 @@ static unsigned long usb_stor_read(struct blk_desc
*block_dev,lbaint_tblknr,Quoted 26 lines
common/usb_storage.c +10
-4/* XXX need some comment here */ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_read: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_read_10 (srb, ss, start, smallblks)) {debug ("Read ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size;
Quoted 9 lines
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, · line 1184
Quoted 5 lines
common/usb_storage.c +4
-0+ usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it;What is the reason for having the same code twice in this patch ? Just pull the identical stuff into a function.
Ok, I will add above code in function namely dec_cur_xfer_blks/ inc_cur_xfer_blks in v3.
Best Regards,
Rajesh Bhagat
Quoted 111 lines
common/usb_storage.c static unsigned long usb_stor_write(struct blk_desc
Quoted 29 lines
common/usb_storage.c +11
-1+ } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;@@ -1181,7 +1206,7 @@ retry_it: start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt; }@@ -1199,11 +1224,13 @@ static unsigned long usb_stor_write(struct blk_desc
*block_dev,lbaint_tblknr,common/usb_storage.c static unsigned long usb_stor_write(struct blk_desc
Quoted 15 lines
common/usb_storage.c +3
-1unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);if (blkcnt ==0 )return 0 ;@@ -1239,26 +1266,46 @@ static unsigned long usb_stor_write(struct blk_desc
*block_dev,lbaint_tblknr,Quoted 52 lines
common/usb_storage.c +24
-4*/ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_write: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_write_10 (srb, ss, start, smallblks)) {debug ("Write ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size; + usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it; + } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;common/usb_storage.c retry_it: · line 1319
Quoted 8 lines
common/usb_storage.c +1
-1@@ -1266,7 +1313,7 @@ retry_it: PRIxPTR "\n", start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt;--
Best regards,
Marek Vasut
PATCH v2 1/1 common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks
Quoted 56 lines · Rajesh Bhagat
Quoted 45 lines
-----Original Message-----
From: Marek Vasut [mailto:marex at denx.de]
Sent: Saturday, June 04, 2016 4:22 AM
To: Rajesh Bhagat <[email protected]>; u-boot at lists.denx.de
Cc: sjg at chromium.org; york sun <[email protected]>; Sriram Dash <[email protected]>
Subject: Re: [PATCH v2] common:usb_storage: Implement logic to calculate optimal usb maximum trasfer blocksQuoted 31 lines · Rajesh Bhagat
Implements the logic to calculate the optimal usb maximum trasfer blocks instead of sending
USB_MAX_XFER_BLKblocks which is 65535 and 20 in case of EHCI and other USB protocols respectively.It defines USB_MIN_XFER_BLK/USB_MAX_XFER_BLK trasfer blocks that should be checked for success starting from minimum to maximum, and rest of the read/write are performed with that optimal value. It tries to increase/ decrease the blocks in follwing scenarios:
1.decrease blocks: when read/write for a particular number of blocks fails.
2. increase blocks: when read/write for a particular number of blocks pass and amount left to trasfer is greater than current number of blocks.Currently changes are done for EHCI where min = 4096 and max = 65535 is taken. And for other cases code is left unchanged by keeping min = max = 20.
Signed-off-by Sriram Dash <[email protected]>Signed-off-by Rajesh Bhagat <[email protected]>--- common/usb_storage.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-)common/usb_storage.c index renamed from common/usb_storage.c +0
-07e6e52d..eee8f4c 100644
common/usb_storage.c struct us_data { · line 106
Quoted 1 line
common/usb_storage.c +0
-0@@ -106,10 +106,13 @@ struct us_data {* enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
Quoted 10 lines
common/usb_storage.c struct us_data { · line 115
Quoted 9 lines
common/usb_storage.c +3
-0* limited to 65535 blocks. */ +#define USB_MIN_XFER_BLK 4095#define USB_MAX_XFER_BLK 65535#else +#define USB_MIN_XFER_BLK 20#define USB_MAX_XFER_BLK 20#endif +#define USB_CUR_XFER_BLK (n) (n >= 0 ? ((1 << (12 + (n))) - 1) : 0)
Quoted 8 lines
Hello Marek,
Quoted 3 lines
Can this be ever called with n < 0 ? You should make this into a function to get typechecking on it too.
Yes. When transfer fails for the first time (pos - 1) is passed to this macro. Ok, I will convert it to a function in v3.
This should be handled outside of the macro then.
Quoted 20 lines
Quoted 4 lines
common/usb_storage.c struct us_data { · line 118
Quoted 3 lines
common/usb_storage.c +1
-0#ifndef CONFIG_BLK static struct us_data usb_stor[USB_MAX_STOR_DEV]; @@ -1117,11 +1120,13 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev,
lbaint_tblknr,Quoted 15 lines
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, · line 1129
Quoted 11 lines
common/usb_storage.c +3
-1unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);How will this behave if you keep alternating between two
block_devdevices ? It will always start looking for the best possible transfer length from scratch, right ? That's not great ...
Quoted 2 lines
How about adding a field name "
cur_xfer_blks" in structusb_deviceand updating it on device basis , it will help retain the value.
That might work, yes.
Quoted 162 lines
struct
usb_device{
...unsigned short cur_xfer_blks; };Quoted 31 lines
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc
Quoted 4 lines
common/usb_storage.c +0
-0if (blkcnt ==0 )return 0 ;@@ -1153,26 +1158,46 @@ static unsigned long usb_stor_read(struct blk_desc
*block_dev,lbaint_tblknr,Quoted 26 lines
common/usb_storage.c +10
-4/* XXX need some comment here */ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_read: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_read_10 (srb, ss, start, smallblks)) {debug ("Read ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size;Quoted 9 lines
common/usb_storage.c static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, · line 1184
Quoted 5 lines
common/usb_storage.c +4
-0+ usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it;What is the reason for having the same code twice in this patch ? Just pull the identical stuff into a function.
Ok, I will add above code in function namely dec_cur_xfer_blks/
inc_cur_xfer_blksin v3.Best Regards,
Rajesh BhagatQuoted 111 lines
common/usb_storage.c static unsigned long usb_stor_write(struct blk_desc
Quoted 29 lines
common/usb_storage.c +11
-1+ } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;@@ -1181,7 +1206,7 @@ retry_it: start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt; }@@ -1199,11 +1224,13 @@ static unsigned long usb_stor_write(struct blk_desc
*block_dev,lbaint_tblknr,common/usb_storage.c static unsigned long usb_stor_write(struct blk_desc
Quoted 15 lines
common/usb_storage.c +3
-1unsigned short smallblks;struct usb_device *udev;struct us_data *ss; -int retry; +int retry, pos =0 ; +bool retry_flag = false;ccb *srb = &usb_ccb;#ifdef CONFIG_BLK struct blk_desc *block_dev;#endif +unsigned short usb_cur_xfer_blk =USB_CUR_XFER_BLK (pos);if (blkcnt ==0 )return 0 ;@@ -1239,26 +1266,46 @@ static unsigned long usb_stor_write(struct blk_desc
*block_dev,lbaint_tblknr,Quoted 52 lines
common/usb_storage.c +24
-4*/ retry =2 ; srb->pdata = (unsigned char *)buf_addr; -if (blks >USB_MAX_XFER_BLK ) - smallblks =USB_MAX_XFER_BLK ; +if (blks > usb_cur_xfer_blk) + smallblks = usb_cur_xfer_blk;else smallblks = (unsigned short ) blks; retry_it: -if (smallblks ==USB_MAX_XFER_BLK ) +debug ("usb_write: retry #%d, usb_cur_xfer_blk %hu, smallblks %hu\n" , + retry, usb_cur_xfer_blk, smallblks); +if (smallblks == usb_cur_xfer_blk)usb_show_progress (); srb->datalen = block_dev->blksz * smallblks; srb->pdata = (unsigned char *)buf_addr;if (usb_write_10 (srb, ss, start, smallblks)) {debug ("Write ERROR\n" );usb_request_sense (srb, ss); -if (retry--) +if (retry--) { +/* decrease the usb_cur_xfer_blk */ +unsigned short size =USB_CUR_XFER_BLK (pos -1 ); +if (size >=USB_MIN_XFER_BLK ) { + smallblks = size; + usb_cur_xfer_blk = smallblks; + pos--; + } + retry_flag = true; goto retry_it; + } blkcnt -= blks;break ; } start += smallblks; blks -= smallblks; buf_addr += srb->datalen; + +/* try to increase the usb_cur_xfer_blk */ +if (!retry_flag) { +unsigned short size =USB_CUR_XFER_BLK (pos +1 ); +if (size <= blks && size <=USB_MAX_XFER_BLK ) { + usb_cur_xfer_blk = size; + pos++; + } + } }while (blks !=0 ); ss->flags &= ~USB_READY ;common/usb_storage.c retry_it: · line 1319
Quoted 8 lines
common/usb_storage.c +1
-1@@ -1266,7 +1313,7 @@ retry_it: PRIxPTR "\n", start, smallblks, buf_addr);usb_disable_asynch (0 );/* asynch transfer allowed */ -if (blkcnt >=USB_MAX_XFER_BLK ) +if (blkcnt >= usb_cur_xfer_blk)debug ("\n" );return blkcnt;--
Best regards,
Marek Vasut
Signature · 2 lines
Best regards, Marek Vasut