From 5bf9bdcf0b2e3b4b9161c55713d8004ce6924900 Mon Sep 17 00:00:00 2001 From: Gene Cumm Date: Wed, 27 Nov 2013 16:48:55 -0500 Subject: efi: Loop on Configure when EFI_NO_MAPPING in udp.c/tcp.c This should help hardware that doesn't return EFI_SUCCESS immediately. Reported-by: Jason Matthews Signed-off-by: Gene Cumm --- efi/efi.h | 5 +++++ efi/tcp.c | 19 ++++++++++++++++++- efi/udp.c | 46 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/efi/efi.h b/efi/efi.h index 9e4a4432..ef5bacb3 100644 --- a/efi/efi.h +++ b/efi/efi.h @@ -24,6 +24,11 @@ #include #include +/* Delay for 100 ms */ +#define EFI_NOMAP_PRINT_DELAY 100 +/* We should keep EFI_NOMAP_PRINT_COUNT at 10 to limit flooding the console */ +#define EFI_NOMAP_PRINT_COUNT 10 + struct efi_disk_private { EFI_HANDLE dev_handle; EFI_BLOCK_IO *bio; diff --git a/efi/tcp.c b/efi/tcp.c index 274456d0..f4dfc7e8 100644 --- a/efi/tcp.c +++ b/efi/tcp.c @@ -52,6 +52,8 @@ int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port) EFI_STATUS status; EFI_TCP4 *tcp = (EFI_TCP4 *)b->this; int rv = -1; + int unmapped = 1; + jiffies_t start, last, cur; memset(&tdata, 0, sizeof(tdata)); @@ -63,7 +65,22 @@ int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port) tdata.TimeToLive = 64; - status = uefi_call_wrapper(tcp->Configure, 2, tcp, &tdata); + last = start = jiffies(); + while (unmapped){ + status = uefi_call_wrapper(tcp->Configure, 2, tcp, &tdata); + if (status != EFI_NO_MAPPING) + unmapped = 0; + else { + cur = jiffies(); + if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) { + last = cur; + Print(L"core_tcp_connect: stalling on configure with no mapping\n"); + } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY * EFI_NOMAP_PRINT_COUNT) { + Print(L"core_tcp_connect: aborting on no mapping\n"); + unmapped = 0; + } + } + } if (status != EFI_SUCCESS) return -1; diff --git a/efi/udp.c b/efi/udp.c index 744ff0f6..30a8c777 100644 --- a/efi/udp.c +++ b/efi/udp.c @@ -14,6 +14,42 @@ extern EFI_GUID Udp4ServiceBindingProtocol, Udp4Protocol; */ static struct efi_binding *udp_reader; +/** + * Try to configure this UDP socket + * + * @param:udp, the EFI_UDP4 socket to configure + * @param:udata, the EFI_UDP4_CONFIG_DATA to use + * @param:f, the name of the function as a wide string. + * + * @out: status as EFI_STATUS + */ + +EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata, + short unsigned int *f) +{ + EFI_STATUS status; + int unmapped = 1; + jiffies_t start, last, cur; + + last = start = jiffies(); + while (unmapped){ + status = uefi_call_wrapper(udp->Configure, 2, udp, udata); + if (status != EFI_NO_MAPPING) + unmapped = 0; + else { + cur = jiffies(); + if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) { + last = cur; + Print(L"%s: stalling on configure with no mapping\n", f); + } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY * EFI_NOMAP_PRINT_COUNT) { + Print(L"%s: aborting on no mapping\n", f); + unmapped = 0; + } + } + } + return status; +} + /** * Open a socket * @@ -42,7 +78,7 @@ int core_udp_open(struct pxe_pvt_inode *socket) memset(&udata, 0, sizeof(udata)); - status = uefi_call_wrapper(udp->Configure, 2, udp, &udata); + status = core_udp_configure(udp, &udata, L"core_udp_open"); if (status != EFI_SUCCESS) goto bail; @@ -116,7 +152,7 @@ void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip, udata.AcceptPromiscuous = TRUE; udata.TimeToLive = 64; - status = uefi_call_wrapper(udp->Configure, 2, udp, &udata); + status = core_udp_configure(udp, &udata, L"core_udp_connect"); if (status != EFI_SUCCESS) { Print(L"Failed to configure UDP: %d\n", status); return; @@ -263,8 +299,6 @@ void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len) if (status != EFI_SUCCESS) goto bail; - txdata->UdpSessionData = NULL; - txdata->GatewayAddress = NULL; txdata->DataLength = len; txdata->FragmentCount = 1; frag = &txdata->FragmentTable[0]; @@ -339,7 +373,7 @@ void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data, udata.AcceptPromiscuous = TRUE; udata.TimeToLive = 64; - status = uefi_call_wrapper(udp->Configure, 2, udp, &udata); + status = core_udp_configure(udp, &udata, L"core_udp_sendto"); if (status != EFI_SUCCESS) goto bail; @@ -348,8 +382,6 @@ void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data, if (status != EFI_SUCCESS) goto bail; - txdata->UdpSessionData = NULL; - txdata->GatewayAddress = NULL; txdata->DataLength = len; txdata->FragmentCount = 1; frag = &txdata->FragmentTable[0]; -- cgit v1.2.3