All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Vasut <marex@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/2] common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks
Date: Tue, 31 May 2016 01:41:50 +0200	[thread overview]
Message-ID: <574CCFBE.3020808@denx.de> (raw)
In-Reply-To: <1464607435-2639-2-git-send-email-rajesh.bhagat@nxp.com>

On 05/30/2016 01:23 PM, Rajesh Bhagat wrote:
> 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 adds an array of 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 andmax = 65535
> is taken. And for other cases code is left unchanged by keeping min
> = max = 20.
> 
> Signed-off-by: Sriram Dash <sriram.dash@nxp.com>
> Signed-off-by: Rajesh Bhagat <rajesh.bhagat@nxp.com>
> ---
>  common/usb_storage.c |   54 ++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 43 insertions(+), 11 deletions(-)
> 
> diff --git a/common/usb_storage.c b/common/usb_storage.c
> index 7e6e52d..7b5ad07 100644
> --- a/common/usb_storage.c
> +++ b/common/usb_storage.c
> @@ -101,16 +101,15 @@ struct us_data {
>  };
>  
>  #ifdef CONFIG_USB_EHCI
> -/*
> - * The U-Boot EHCI driver can handle any transfer length as long as there is
> - * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
> - * limited to 65535 blocks.
> - */
> -#define USB_MAX_XFER_BLK	65535
> +#define USB_XFER_BLK_TBL_SZ		5
> +static unsigned short usb_xfer_blk_tbl[5] = {4096, 8192, 16384, 32768, 65535};

You should stick to using one block less than the power of two, the
controllers react to that a bit better. Each value in this table can
then be calculated really trivially, it's:

(1 << (12 + n)) - 1

You also don't need such static data.

>  #else
> -#define USB_MAX_XFER_BLK	20
> +#define USB_XFER_BLK_TBL_SZ		1
> +static unsigned short usb_xfer_blk_tbl[1] = {20};
>  #endif
>  
> +static unsigned short USB_MAX_XFER_BLK;

This value is different on per-device basis, how can it be static data ?

>  #ifndef CONFIG_BLK
>  static struct us_data usb_stor[USB_MAX_STOR_DEV];
>  #endif
> @@ -1117,7 +1116,8 @@ 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, next = LOG2((USB_MAX_XFER_BLK + 1) / usb_xfer_blk_tbl[0]);
> +	bool retry_flag = false;
>  	ccb *srb = &usb_ccb;
>  #ifdef CONFIG_BLK
>  	struct blk_desc *block_dev;
> @@ -1158,6 +1158,8 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
>  		else
>  			smallblks = (unsigned short) blks;
>  retry_it:
> +		debug("usb_read: retry #%d, xfer_blk %hu, smallblks %hu\n",
> +		      retry, USB_MAX_XFER_BLK, smallblks);
>  		if (smallblks == USB_MAX_XFER_BLK)
>  			usb_show_progress();
>  		srb->datalen = block_dev->blksz * smallblks;
> @@ -1165,14 +1167,26 @@ retry_it:
>  		if (usb_read_10(srb, ss, start, smallblks)) {
>  			debug("Read ERROR\n");
>  			usb_request_sense(srb, ss);
> -			if (retry--)
> +			if (retry--) {
> +				/* decrease the USB_MAX_XFER_BLK */
> +				if (next >  0) {
> +					smallblks = usb_xfer_blk_tbl[--next];
> +					USB_MAX_XFER_BLK = smallblks;
> +				}
> +				retry_flag = true;
>  				goto retry_it;
> +			}
>  			blkcnt -= blks;
>  			break;
>  		}
>  		start += smallblks;
>  		blks -= smallblks;
>  		buf_addr += srb->datalen;
> +
> +		/* try to increase the USB_MAX_XFER_BLK */
> +		if (next < USB_XFER_BLK_TBL_SZ  - 1)
> +			if (!retry_flag && usb_xfer_blk_tbl[next + 1] <= blks)
> +				USB_MAX_XFER_BLK = usb_xfer_blk_tbl[++next];
>  	} while (blks != 0);
>  	ss->flags &= ~USB_READY;
>  
> @@ -1199,7 +1213,8 @@ 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, next = LOG2((USB_MAX_XFER_BLK + 1) / usb_xfer_blk_tbl[0]);
> +	bool retry_flag = false;
>  	ccb *srb = &usb_ccb;
>  #ifdef CONFIG_BLK
>  	struct blk_desc *block_dev;
> @@ -1244,6 +1259,8 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
>  		else
>  			smallblks = (unsigned short) blks;
>  retry_it:
> +		debug("usb_write: retry #%d, xfer_blk %hu, smallblks %hu\n",
> +		      retry, USB_MAX_XFER_BLK, smallblks);
>  		if (smallblks == USB_MAX_XFER_BLK)
>  			usb_show_progress();
>  		srb->datalen = block_dev->blksz * smallblks;
> @@ -1251,14 +1268,26 @@ retry_it:
>  		if (usb_write_10(srb, ss, start, smallblks)) {
>  			debug("Write ERROR\n");
>  			usb_request_sense(srb, ss);
> -			if (retry--)
> +			if (retry--) {
> +				/* decrease the USB_MAX_XFER_BLK */
> +				if (next >  0) {
> +					smallblks = usb_xfer_blk_tbl[--next];
> +					USB_MAX_XFER_BLK = smallblks;
> +				}
> +				retry_flag = true;
>  				goto retry_it;
> +			}
>  			blkcnt -= blks;
>  			break;
>  		}
>  		start += smallblks;
>  		blks -= smallblks;
>  		buf_addr += srb->datalen;
> +
> +		/* try to increase the USB_MAX_XFER_BLK */
> +		if (next < USB_XFER_BLK_TBL_SZ  - 1)
> +			if (!retry_flag && usb_xfer_blk_tbl[next + 1] <= blks)
> +				USB_MAX_XFER_BLK = usb_xfer_blk_tbl[++next];
>  	} while (blks != 0);
>  	ss->flags &= ~USB_READY;
>  
> @@ -1331,6 +1360,9 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
>  		break;
>  	}
>  
> +	/* Initialize the current transfer blocks to minimum value */
> +	USB_MAX_XFER_BLK = usb_xfer_blk_tbl[0];
> +
>  	/*
>  	 * We are expecting a minimum of 2 endpoints - in and out (bulk).
>  	 * An optional interrupt is OK (necessary for CBI protocol).
> 


-- 
Best regards,
Marek Vasut

  reply	other threads:[~2016-05-30 23:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-30 11:23 [U-Boot] [PATCH 0/2] common: usb_storage : Implement logic to calculate optimal Rajesh Bhagat
2016-05-30 11:23 ` [U-Boot] [PATCH 1/2] common: usb_storage : Implement logic to calculate optimal usb maximum trasfer blocks Rajesh Bhagat
2016-05-30 23:41   ` Marek Vasut [this message]
2016-05-31  3:23     ` Rajesh Bhagat
2016-05-31 11:56       ` Marek Vasut
2016-06-01  3:47         ` Rajesh Bhagat
2016-05-30 11:23 ` [U-Boot] [PATCH 2/2] common: usb_storage : Seperate optimal blocks logic calculation for read/write Rajesh Bhagat

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=574CCFBE.3020808@denx.de \
    --to=marex@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.