[usb] Allow USB endpoints to specify a reserved header length for refills

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2016-01-19 00:01:11 +00:00
parent 8dc23d9b83
commit 71b83a6d00
11 changed files with 31 additions and 20 deletions

View File

@@ -601,6 +601,7 @@ void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf,
*/ */
int usb_prefill ( struct usb_endpoint *ep ) { int usb_prefill ( struct usb_endpoint *ep ) {
struct io_buffer *iobuf; struct io_buffer *iobuf;
size_t reserve = ep->reserve;
size_t len = ( ep->len ? ep->len : ep->mtu ); size_t len = ( ep->len ? ep->len : ep->mtu );
unsigned int fill; unsigned int fill;
int rc; int rc;
@@ -614,11 +615,12 @@ int usb_prefill ( struct usb_endpoint *ep ) {
for ( fill = 0 ; fill < ep->max ; fill++ ) { for ( fill = 0 ; fill < ep->max ; fill++ ) {
/* Allocate I/O buffer */ /* Allocate I/O buffer */
iobuf = alloc_iob ( len ); iobuf = alloc_iob ( reserve + len );
if ( ! iobuf ) { if ( ! iobuf ) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_alloc; goto err_alloc;
} }
iob_reserve ( iobuf, reserve );
/* Add to recycled buffer list */ /* Add to recycled buffer list */
list_add_tail ( &iobuf->list, &ep->recycled ); list_add_tail ( &iobuf->list, &ep->recycled );
@@ -639,6 +641,7 @@ int usb_prefill ( struct usb_endpoint *ep ) {
*/ */
int usb_refill ( struct usb_endpoint *ep ) { int usb_refill ( struct usb_endpoint *ep ) {
struct io_buffer *iobuf; struct io_buffer *iobuf;
size_t reserve = ep->reserve;
size_t len = ( ep->len ? ep->len : ep->mtu ); size_t len = ( ep->len ? ep->len : ep->mtu );
int rc; int rc;
@@ -652,9 +655,10 @@ int usb_refill ( struct usb_endpoint *ep ) {
/* Get or allocate buffer */ /* Get or allocate buffer */
if ( list_empty ( &ep->recycled ) ) { if ( list_empty ( &ep->recycled ) ) {
/* Recycled buffer list is empty; allocate new buffer */ /* Recycled buffer list is empty; allocate new buffer */
iobuf = alloc_iob ( len ); iobuf = alloc_iob ( reserve + len );
if ( ! iobuf ) if ( ! iobuf )
return -ENOMEM; return -ENOMEM;
iob_reserve ( iobuf, reserve );
} else { } else {
/* Get buffer from recycled buffer list */ /* Get buffer from recycled buffer list */
iobuf = list_first_entry ( &ep->recycled, iobuf = list_first_entry ( &ep->recycled,

View File

@@ -447,8 +447,8 @@ static int acm_probe ( struct usb_function *func,
acm->rndis = rndis; acm->rndis = rndis;
usbnet_init ( &acm->usbnet, func, &acm_intr_operations, usbnet_init ( &acm->usbnet, func, &acm_intr_operations,
&acm_in_operations, &acm_out_operations ); &acm_in_operations, &acm_out_operations );
usb_refill_init ( &acm->usbnet.intr, 0, ACM_INTR_MAX_FILL ); usb_refill_init ( &acm->usbnet.intr, 0, 0, ACM_INTR_MAX_FILL );
usb_refill_init ( &acm->usbnet.in, ACM_IN_MTU, ACM_IN_MAX_FILL ); usb_refill_init ( &acm->usbnet.in, 0, ACM_IN_MTU, ACM_IN_MAX_FILL );
/* Describe USB network device */ /* Describe USB network device */
if ( ( rc = usbnet_describe ( &acm->usbnet, config ) ) != 0 ) { if ( ( rc = usbnet_describe ( &acm->usbnet, config ) ) != 0 ) {

View File

@@ -532,8 +532,8 @@ static int dm96xx_probe ( struct usb_function *func,
dm96xx->netdev = netdev; dm96xx->netdev = netdev;
usbnet_init ( &dm96xx->usbnet, func, &dm96xx_intr_operations, usbnet_init ( &dm96xx->usbnet, func, &dm96xx_intr_operations,
&dm96xx_in_operations, &dm96xx_out_operations ); &dm96xx_in_operations, &dm96xx_out_operations );
usb_refill_init ( &dm96xx->usbnet.intr, 0, DM96XX_INTR_MAX_FILL ); usb_refill_init ( &dm96xx->usbnet.intr, 0, 0, DM96XX_INTR_MAX_FILL );
usb_refill_init ( &dm96xx->usbnet.in, DM96XX_IN_MTU, usb_refill_init ( &dm96xx->usbnet.in, 0, DM96XX_IN_MTU,
DM96XX_IN_MAX_FILL ); DM96XX_IN_MAX_FILL );
DBGC ( dm96xx, "DM96XX %p on %s\n", dm96xx, func->name ); DBGC ( dm96xx, "DM96XX %p on %s\n", dm96xx, func->name );

View File

@@ -437,8 +437,8 @@ static int ecm_probe ( struct usb_function *func,
ecm->netdev = netdev; ecm->netdev = netdev;
usbnet_init ( &ecm->usbnet, func, &ecm_intr_operations, usbnet_init ( &ecm->usbnet, func, &ecm_intr_operations,
&ecm_in_operations, &ecm_out_operations ); &ecm_in_operations, &ecm_out_operations );
usb_refill_init ( &ecm->usbnet.intr, 0, ECM_INTR_MAX_FILL ); usb_refill_init ( &ecm->usbnet.intr, 0, 0, ECM_INTR_MAX_FILL );
usb_refill_init ( &ecm->usbnet.in, ECM_IN_MTU, ECM_IN_MAX_FILL ); usb_refill_init ( &ecm->usbnet.in, 0, ECM_IN_MTU, ECM_IN_MAX_FILL );
DBGC ( ecm, "ECM %p on %s\n", ecm, func->name ); DBGC ( ecm, "ECM %p on %s\n", ecm, func->name );
/* Describe USB network device */ /* Describe USB network device */

View File

@@ -186,7 +186,7 @@ static int ncm_in_prefill ( struct ncm_device *ncm ) {
count = NCM_IN_MIN_COUNT; count = NCM_IN_MIN_COUNT;
if ( ( count * mtu ) > NCM_IN_MAX_SIZE ) if ( ( count * mtu ) > NCM_IN_MAX_SIZE )
continue; continue;
usb_refill_init ( &ncm->usbnet.in, mtu, count ); usb_refill_init ( &ncm->usbnet.in, 0, mtu, count );
if ( ( rc = usb_prefill ( &ncm->usbnet.in ) ) != 0 ) { if ( ( rc = usb_prefill ( &ncm->usbnet.in ) ) != 0 ) {
DBGC ( ncm, "NCM %p could not prefill %dx %zd-byte " DBGC ( ncm, "NCM %p could not prefill %dx %zd-byte "
"buffers for bulk IN\n", ncm, count, mtu ); "buffers for bulk IN\n", ncm, count, mtu );
@@ -575,7 +575,7 @@ static int ncm_probe ( struct usb_function *func,
ncm->netdev = netdev; ncm->netdev = netdev;
usbnet_init ( &ncm->usbnet, func, &ncm_intr_operations, usbnet_init ( &ncm->usbnet, func, &ncm_intr_operations,
&ncm_in_operations, &ncm_out_operations ); &ncm_in_operations, &ncm_out_operations );
usb_refill_init ( &ncm->usbnet.intr, 0, NCM_INTR_COUNT ); usb_refill_init ( &ncm->usbnet.intr, 0, 0, NCM_INTR_COUNT );
DBGC ( ncm, "NCM %p on %s\n", ncm, func->name ); DBGC ( ncm, "NCM %p on %s\n", ncm, func->name );
/* Describe USB network device */ /* Describe USB network device */

View File

@@ -979,8 +979,9 @@ static int smsc75xx_probe ( struct usb_function *func,
smsc75xx->netdev = netdev; smsc75xx->netdev = netdev;
usbnet_init ( &smsc75xx->usbnet, func, &smsc75xx_intr_operations, usbnet_init ( &smsc75xx->usbnet, func, &smsc75xx_intr_operations,
&smsc75xx_in_operations, &smsc75xx_out_operations ); &smsc75xx_in_operations, &smsc75xx_out_operations );
usb_refill_init ( &smsc75xx->usbnet.intr, 0, SMSC75XX_INTR_MAX_FILL ); usb_refill_init ( &smsc75xx->usbnet.intr, 0, 0,
usb_refill_init ( &smsc75xx->usbnet.in, SMSC75XX_IN_MTU, SMSC75XX_INTR_MAX_FILL );
usb_refill_init ( &smsc75xx->usbnet.in, 0, SMSC75XX_IN_MTU,
SMSC75XX_IN_MAX_FILL ); SMSC75XX_IN_MAX_FILL );
mii_init ( &smsc75xx->mii, &smsc75xx_mii_operations ); mii_init ( &smsc75xx->mii, &smsc75xx_mii_operations );
DBGC ( smsc75xx, "SMSC75XX %p on %s\n", smsc75xx, func->name ); DBGC ( smsc75xx, "SMSC75XX %p on %s\n", smsc75xx, func->name );

View File

@@ -1140,8 +1140,9 @@ static int smsc95xx_probe ( struct usb_function *func,
smsc95xx->netdev = netdev; smsc95xx->netdev = netdev;
usbnet_init ( &smsc95xx->usbnet, func, &smsc95xx_intr_operations, usbnet_init ( &smsc95xx->usbnet, func, &smsc95xx_intr_operations,
&smsc95xx_in_operations, &smsc95xx_out_operations ); &smsc95xx_in_operations, &smsc95xx_out_operations );
usb_refill_init ( &smsc95xx->usbnet.intr, 0, SMSC95XX_INTR_MAX_FILL ); usb_refill_init ( &smsc95xx->usbnet.intr, 0, 0,
usb_refill_init ( &smsc95xx->usbnet.in, SMSC95XX_IN_MTU, SMSC95XX_INTR_MAX_FILL );
usb_refill_init ( &smsc95xx->usbnet.in, 0, SMSC95XX_IN_MTU,
SMSC95XX_IN_MAX_FILL ); SMSC95XX_IN_MAX_FILL );
mii_init ( &smsc95xx->mii, &smsc95xx_mii_operations ); mii_init ( &smsc95xx->mii, &smsc95xx_mii_operations );
DBGC ( smsc95xx, "SMSC95XX %p on %s\n", smsc95xx, func->name ); DBGC ( smsc95xx, "SMSC95XX %p on %s\n", smsc95xx, func->name );

View File

@@ -416,7 +416,7 @@ static int hub_probe ( struct usb_function *func,
( enhanced ? USB_HUB_FEATURES_ENHANCED : USB_HUB_FEATURES ); ( enhanced ? USB_HUB_FEATURES_ENHANCED : USB_HUB_FEATURES );
hubdev->flags = func->id->driver_data; hubdev->flags = func->id->driver_data;
usb_endpoint_init ( &hubdev->intr, usb, &usb_hub_intr_operations ); usb_endpoint_init ( &hubdev->intr, usb, &usb_hub_intr_operations );
usb_refill_init ( &hubdev->intr, 0, USB_HUB_INTR_FILL ); usb_refill_init ( &hubdev->intr, 0, 0, USB_HUB_INTR_FILL );
process_init_stopped ( &hubdev->refill, &hub_refill_desc, NULL ); process_init_stopped ( &hubdev->refill, &hub_refill_desc, NULL );
/* Locate hub interface descriptor */ /* Locate hub interface descriptor */

View File

@@ -425,7 +425,7 @@ static int usbkbd_probe ( struct usb_function *func,
kbd->name = func->name; kbd->name = func->name;
kbd->bus = usb->port->hub->bus; kbd->bus = usb->port->hub->bus;
usbhid_init ( &kbd->hid, func, &usbkbd_operations, NULL ); usbhid_init ( &kbd->hid, func, &usbkbd_operations, NULL );
usb_refill_init ( &kbd->hid.in, sizeof ( kbd->report ), usb_refill_init ( &kbd->hid.in, 0, sizeof ( kbd->report ),
USBKBD_INTR_MAX_FILL ); USBKBD_INTR_MAX_FILL );
/* Describe USB human interface device */ /* Describe USB human interface device */

View File

@@ -414,7 +414,9 @@ struct usb_endpoint {
/** Recycled I/O buffer list */ /** Recycled I/O buffer list */
struct list_head recycled; struct list_head recycled;
/** Refill buffer length */ /** Refill buffer reserved header length */
size_t reserve;
/** Refill buffer payload length */
size_t len; size_t len;
/** Maximum fill level */ /** Maximum fill level */
unsigned int max; unsigned int max;
@@ -588,13 +590,16 @@ extern void usb_complete_err ( struct usb_endpoint *ep,
* Initialise USB endpoint refill * Initialise USB endpoint refill
* *
* @v ep USB endpoint * @v ep USB endpoint
* @v len Refill buffer length (or zero to use endpoint's MTU) * @v reserve Refill buffer reserved header length
* @v len Refill buffer payload length (zero for endpoint's MTU)
* @v max Maximum fill level * @v max Maximum fill level
*/ */
static inline __attribute__ (( always_inline )) void static inline __attribute__ (( always_inline )) void
usb_refill_init ( struct usb_endpoint *ep, size_t len, unsigned int max ) { usb_refill_init ( struct usb_endpoint *ep, size_t reserve, size_t len,
unsigned int max ) {
INIT_LIST_HEAD ( &ep->recycled ); INIT_LIST_HEAD ( &ep->recycled );
ep->reserve = reserve;
ep->len = len; ep->len = len;
ep->max = max; ep->max = max;
} }

View File

@@ -472,7 +472,7 @@ static int efi_usb_async_start ( struct efi_usb_interface *usbintf,
usbep->context = context; usbep->context = context;
/* Prefill endpoint */ /* Prefill endpoint */
usb_refill_init ( &usbep->ep, len, EFI_USB_ASYNC_FILL ); usb_refill_init ( &usbep->ep, 0, len, EFI_USB_ASYNC_FILL );
if ( ( rc = usb_prefill ( &usbep->ep ) ) != 0 ) { if ( ( rc = usb_prefill ( &usbep->ep ) ) != 0 ) {
DBGC ( usbdev, "USBDEV %s %s could not prefill: %s\n", DBGC ( usbdev, "USBDEV %s %s could not prefill: %s\n",
usbintf->name, usb_endpoint_name ( &usbep->ep ), usbintf->name, usb_endpoint_name ( &usbep->ep ),