[syslinux:master] efi: Loop on Configure when EFI_NO_MAPPING in udp.c/tcp.c

syslinux-bot for Gene Cumm gene.cumm at gmail.com
Fri Jan 31 21:42:07 PST 2014


Commit-ID:  5bf9bdcf0b2e3b4b9161c55713d8004ce6924900
Gitweb:     http://www.syslinux.org/commit/5bf9bdcf0b2e3b4b9161c55713d8004ce6924900
Author:     Gene Cumm <gene.cumm at gmail.com>
AuthorDate: Wed, 27 Nov 2013 16:48:55 -0500
Committer:  Gene Cumm <gene.cumm at gmail.com>
CommitDate: Wed, 29 Jan 2014 11:55:14 -0500

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 <jason.david.matthews at gmail.com>
Signed-off-by: Gene Cumm <gene.cumm at gmail.com>

---
 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 9e4a443..ef5bacb 100644
--- a/efi/efi.h
+++ b/efi/efi.h
@@ -24,6 +24,11 @@
 #include <efilib.h>
 #include <efistdarg.h>
 
+/* 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 274456d..f4dfc7e 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 744ff0f..30a8c77 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];


More information about the Syslinux-commits mailing list