|
|
28f7f8 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
ecb9bb |
From: Andrei Borzenkov <arvidjaar@gmail.com>
|
|
|
ecb9bb |
Date: Thu, 7 May 2015 20:37:17 +0300
|
|
|
28f7f8 |
Subject: [PATCH] efinet: open Simple Network Protocol exclusively
|
|
|
ecb9bb |
|
|
|
ecb9bb |
EDK2 network stack is based on Managed Network Protocol which is layered
|
|
|
ecb9bb |
on top of Simple Management Protocol and does background polling. This
|
|
|
ecb9bb |
polling races with grub for received (and probably trasmitted) packets
|
|
|
ecb9bb |
which causes either serious slowdown or complete failure to load files.
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Open SNP device exclusively. This destroys all child MNP instances and
|
|
|
ecb9bb |
stops background polling.
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Exclusive open cannot be done when enumerating cards, as it would destroy
|
|
|
ecb9bb |
PXE information we need to autoconfigure interface; and it cannot be done
|
|
|
ecb9bb |
during autoconfiguration as we need to do it for non-PXE boot as well. So
|
|
|
ecb9bb |
move SNP open to card ->open method and add matching ->close to clean up.
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Based on patch from Mark Salter <msalter@redhat.com>
|
|
|
ecb9bb |
|
|
|
ecb9bb |
Also-By: Mark Salter <msalter@redhat.com>
|
|
|
ecb9bb |
Closes: 41731
|
|
|
ecb9bb |
---
|
|
|
ecb9bb |
grub-core/net/drivers/efi/efinet.c | 46 ++++++++++++++++++++++++++++++++++++++
|
|
|
ecb9bb |
1 file changed, 46 insertions(+)
|
|
|
ecb9bb |
|
|
|
ecb9bb |
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
|
|
|
28f7f8 |
index caa7b50228b..6a1dd1f9dff 100644
|
|
|
ecb9bb |
--- a/grub-core/net/drivers/efi/efinet.c
|
|
|
ecb9bb |
+++ b/grub-core/net/drivers/efi/efinet.c
|
|
|
ecb9bb |
@@ -142,9 +142,55 @@ get_card_packet (struct grub_net_card *dev)
|
|
|
ecb9bb |
return nb;
|
|
|
ecb9bb |
}
|
|
|
ecb9bb |
|
|
|
ecb9bb |
+static grub_err_t
|
|
|
ecb9bb |
+open_card (struct grub_net_card *dev)
|
|
|
ecb9bb |
+{
|
|
|
ecb9bb |
+ grub_efi_simple_network_t *net;
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ /* Try to reopen SNP exlusively to close any active MNP protocol instance
|
|
|
ecb9bb |
+ that may compete for packet polling
|
|
|
ecb9bb |
+ */
|
|
|
ecb9bb |
+ net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
|
|
|
ecb9bb |
+ GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
|
|
|
ecb9bb |
+ if (net)
|
|
|
ecb9bb |
+ {
|
|
|
ecb9bb |
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
|
|
|
ecb9bb |
+ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
|
|
|
ecb9bb |
+ return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net start failed",
|
|
|
ecb9bb |
+ dev->name);
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
|
|
|
ecb9bb |
+ return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped",
|
|
|
ecb9bb |
+ dev->name);
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ if (net->mode->state == GRUB_EFI_NETWORK_STARTED
|
|
|
ecb9bb |
+ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
|
|
|
ecb9bb |
+ return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
|
|
|
ecb9bb |
+ dev->name);
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
|
|
|
ecb9bb |
+ dev->efi_net, &net_io_guid,
|
|
|
ecb9bb |
+ grub_efi_image_handle, dev->efi_handle);
|
|
|
ecb9bb |
+ dev->efi_net = net;
|
|
|
ecb9bb |
+ }
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+ /* If it failed we just try to run as best as we can */
|
|
|
ecb9bb |
+ return GRUB_ERR_NONE;
|
|
|
ecb9bb |
+}
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
+static void
|
|
|
ecb9bb |
+close_card (struct grub_net_card *dev)
|
|
|
ecb9bb |
+{
|
|
|
ecb9bb |
+ efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
|
|
|
ecb9bb |
+ dev->efi_net, &net_io_guid,
|
|
|
ecb9bb |
+ grub_efi_image_handle, dev->efi_handle);
|
|
|
ecb9bb |
+}
|
|
|
ecb9bb |
+
|
|
|
ecb9bb |
static struct grub_net_card_driver efidriver =
|
|
|
ecb9bb |
{
|
|
|
ecb9bb |
.name = "efinet",
|
|
|
ecb9bb |
+ .open = open_card,
|
|
|
ecb9bb |
+ .close = close_card,
|
|
|
ecb9bb |
.send = send_card_buffer,
|
|
|
ecb9bb |
.recv = get_card_packet
|
|
|
ecb9bb |
};
|