Uboot下USB xHCI传输速率问题
uboot:uboot 2016.07
kernel:linux 4.9.1
最近遇到uboot下U盘传输速率过低的问题,速度大概只有2MB/S,USB控制器是XHCI。借助USB分析仪抓包,对比kernel和uboot的数据包差异,发现kernel下每个transfer packet大小是120KB,uboot则十分的小(具体数值忘记)。针对这个现象去定位代码,确定问题点在”common/usb_storage.c”的宏定义”USB_MAX_XFER_BLK”。
#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
#else
#define USB_MAX_XFER_BLK 20
#endif
#ifndef CONFIG_BLK
static struct us_data usb_stor[USB_MAX_STOR_DEV];
#endif
由上面代码可以知道USB_MAX_XFER_BLK的值只有20,那么transfer packet size为 20*512/1024=10,即只有10KB,跟kernel的120KB比起来真的小气啊!我们跟随kernel的值,将uboot的值修改为240,但考虑后到兼容OHCI等问题,增加XHCI分支。
#define USB_MAX_XFER_BLK 65535
#elif define CONFIG_USB_XHCI_HCD
#define USB_MAX_XFER_BLK 240
#else
#define USB_MAX_XFER_BLK 20
#endif
编译,烧入,测试,U盘的传输速度即可上到13MB/S了。
USB 125μs一个微帧,传输的数据量是不变的,为什么增大USB_MAX_XFER_BLK就可以增大传输速率呢?因为性价比啊!USB Storage设备在USB协议上面走的是SCSI协议,在每个transfer packet之间都会有CBW和CSW。在一定数据量的情况下,transfer packet size越小,CBW和CSW的数量就越多,这个开销不容小觑了,所以速度就慢了。
uboot 2018怎么改呢?还是在”common/usb_storage.c”,只不过这次我们关注宏定义”USHRT_MAX”。
#if !CONFIG_IS_ENABLED(DM_USB)
#ifdef CONFIG_USB_EHCI_HCD
/*
* 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.
*/
blk = USHRT_MAX;
#else
blk = 20;
#endif
通过查询USHRT_MAX的值为0xf0,即240,我们直接使用该宏定义,还避免了魔鬼数字。修改如下:
#if !CONFIG_IS_ENABLED(DM_USB)
#ifdef CONFIG_USB_EHCI_HCD
/*
* 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.
*/
blk = USHRT_MAX;
#elif define CONFIG_USB_XHCI_HCD
blk = USHRT_MAX;
#else
blk = 20;
#endif
如果觉得240的13MB/S太慢了?那就把这个值改成4096吧!这个速度可以通过基于SSD的U盘测试,具体多少我也忘记了。