grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] efinet: disable MNP background polling


From: HATAYAMA Daisuke
Subject: [PATCH] efinet: disable MNP background polling
Date: Thu, 01 Oct 2015 18:26:55 +0900 (JST)

Currently, as of the commit f348aee7b33dd85e7da62b497a96a7319a0bf9dd,
SNP is exclusively reopened to avoid slowdown or complete failure to
load files due to races between MNP background polling and grub's
receiving and transmitting packets.

This exclusive SNP reopen affects some EFI applications/drivers that
use SNP and causes PXE boot on such systems to fail. Hardware filter
issue fixed by the commit 49426e9fd2e562c73a4f1206f32eff9e424a1a73 is
one example.

The difficulty here is that effects of the exclusive SNP reopen
differs from system to system depending their UEFI firmware
implementations. One system works well with the commit
f348aee7b33dd85e7da62b497a96a7319a0bf9dd only, another system still
needs the commit 49426e9fd2e562c73a4f1206f32eff9e424a1a73, and there
could be other systems where PXE boot still fails.

Actually, PXE boot fails on Fujitsu PRIMEQUEST 2000 series now.

Thus, it seems to me that the exclusive SNP reopen makes grub
maintenance difficult by affecting a variety of systems differently.

Instead, the idea of this patch is to disable MNP background polling
temporarily while grub uses SNP. Then, the race issue must be removed.

I think origianal MNP configuration should be recovered before grub
terminates, but this version doesn't do that because I didn't find a
good place to do so.

Before applying this patch, please revert the following 2 commits
related to the exclusive SNP reopen:

  f348aee7b33dd85e7da62b497a96a7319a0bf9dd
  49426e9fd2e562c73a4f1206f32eff9e424a1a73

I would highly appreciate if someone help testing on your environment
because the origianal slow down issue doesn't occur on Fujitsu
PRIMEQUEST 2000 seriees.
---
 grub-core/net/drivers/efi/efinet.c | 14 ++++++++++++++
 include/grub/efi/api.h             | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/grub-core/net/drivers/efi/efinet.c 
b/grub-core/net/drivers/efi/efinet.c
index c9af01c..a506ab3 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -29,6 +29,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 /* GUID.  */
 static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
 static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
+static grub_efi_guid_t mnp_io_guid = GRUB_EFI_MANAGED_NETWORK_GUID;
 
 static grub_err_t
 send_card_buffer (struct grub_net_card *dev,
@@ -269,6 +270,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char 
**device,
     grub_efi_device_path_t *cdp;
     struct grub_efi_pxe *pxe;
     struct grub_efi_pxe_mode *pxe_mode;
+    grub_efi_managed_network_t *mnp;
+    struct grub_efi_managed_network_config_data m;
+    struct grub_efi_simple_network_mode s;
     if (card->driver != &efidriver)
       continue;
     cdp = grub_efi_get_device_path (card->efi_handle);
@@ -312,6 +316,16 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char 
**device,
                                    &pxe_mode->dhcp_ack,
                                    sizeof (pxe_mode->dhcp_ack),
                                    1, device, path);
+
+    mnp = grub_efi_open_protocol (card->efi_handle, &mnp_io_guid,
+                                 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+    if (mnp
+       && efi_call_3 (mnp->get_mode_data, mnp, &m, &s) == GRUB_EFI_SUCCESS) {
+      m.disable_background_polling = 1;
+      efi_call_2 (mnp->configure, mnp, &m);
+    }
+
     return;
   }
 }
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index e5dd543..e2baba2 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -286,6 +286,11 @@
       { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
   }
 
+#define GRUB_EFI_MANAGED_NETWORK_GUID \
+  { 0x7ab33a91, 0xace5, 0x4326, \
+      { 0xb5, 0x72, 0xe7, 0xee, 0x33, 0xd3, 0x9f, 0x16} \
+  }
+
 struct grub_efi_sal_system_table
 {
   grub_uint32_t signature;
@@ -1559,6 +1564,36 @@ struct grub_efi_block_io
 };
 typedef struct grub_efi_block_io grub_efi_block_io_t;
 
+struct grub_efi_managed_network_config_data
+{
+  grub_uint32_t received_queue_timeout_value;
+  grub_uint32_t transmit_queue_timeout_value;
+  grub_uint16_t protocol_type_filter;
+  grub_efi_boolean_t enable_unicast_receive;
+  grub_efi_boolean_t enable_multicast_receive;
+  grub_efi_boolean_t enable_broadcast_receive;
+  grub_efi_boolean_t enable_promiscuous_receive;
+  grub_efi_boolean_t flush_queues_on_reset;
+  grub_efi_boolean_t enable_receive_timestamps;
+  grub_efi_boolean_t disable_background_polling;
+};
+
+struct grub_efi_managed_network
+{
+  grub_efi_status_t (*get_mode_data) (struct grub_efi_managed_network *this,
+                                     struct 
grub_efi_managed_network_config_data *mnp_config,
+                                     struct grub_efi_simple_network_mode 
*snp_mode);
+  grub_efi_status_t (*configure) (struct grub_efi_managed_network *this,
+                                 struct grub_efi_managed_network_config_data 
*mnp_config);
+  void (*mcast_ip_to_mac) (void);
+  void (*groups) (void);
+  void (*transmit) (void);
+  void (*receive) (void);
+  void (*cancel) (void);
+  void (*poll) (void);
+};
+typedef struct grub_efi_managed_network grub_efi_managed_network_t;
+
 #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]