Blame SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch

f725e3
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
f725e3
From: Andrei Borzenkov <arvidjaar@gmail.com>
f725e3
Date: Tue, 16 Jun 2015 19:52:45 +0300
f725e3
Subject: [PATCH] efinet: enable hardware filters when opening interface
f725e3
f725e3
Exclusive open on SNP will close all existing protocol instances which
f725e3
may disable all receive filters on interface. Reinstall them after we
f725e3
opened protocol exclusively.
f725e3
f725e3
Also follow UEFI specification recommendation and stop interfaces when
f725e3
closing them:
f725e3
f725e3
Unexpected system errors, reboots and hangs can occur if an OS is loaded
f725e3
and the network devices are not Shutdown() and Stopped().
f725e3
f725e3
Also by: Mark Salter <msalter@redhat.com>
f725e3
Closes: 45204
f725e3
---
f725e3
 grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++
f725e3
 include/grub/efi/api.h             | 20 +++++++++++++++++---
f725e3
 2 files changed, 42 insertions(+), 3 deletions(-)
f725e3
f725e3
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
f725e3
index 6a1dd1f9dff..7b8c4a59d10 100644
f725e3
--- a/grub-core/net/drivers/efi/efinet.c
f725e3
+++ b/grub-core/net/drivers/efi/efinet.c
f725e3
@@ -168,6 +168,29 @@ open_card (struct grub_net_card *dev)
f725e3
 	return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
f725e3
 			   dev->name);
f725e3
 
f725e3
+      /* Enable hardware receive filters if driver declares support for it.
f725e3
+	 We need unicast and broadcast and additionaly all nodes and
f725e3
+	 solicited multicast for IPv6. Solicited multicast is per-IPv6
f725e3
+	 address and we currently do not have API to do it so simply
f725e3
+	 try to enable receive of all multicast packets or evertyhing in
f725e3
+	 the worst case (i386 PXE driver always enables promiscuous too).
f725e3
+
f725e3
+	 This does trust firmware to do what it claims to do.
f725e3
+       */
f725e3
+      if (net->mode->receive_filter_mask)
f725e3
+	{
f725e3
+	  grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST   |
f725e3
+				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
f725e3
+				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
f725e3
+
f725e3
+	  filters &= net->mode->receive_filter_mask;
f725e3
+	  if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
f725e3
+	    filters |= (net->mode->receive_filter_mask &
f725e3
+			GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
f725e3
+
f725e3
+	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
f725e3
+	}
f725e3
+
f725e3
       efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
f725e3
 		  dev->efi_net, &net_io_guid,
f725e3
 		  grub_efi_image_handle, dev->efi_handle);
f725e3
@@ -181,6 +204,8 @@ open_card (struct grub_net_card *dev)
f725e3
 static void
f725e3
 close_card (struct grub_net_card *dev)
f725e3
 {
f725e3
+  efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
f725e3
+  efi_call_1 (dev->efi_net->stop, dev->efi_net);
f725e3
   efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
f725e3
 	      dev->efi_net, &net_io_guid,
f725e3
 	      grub_efi_image_handle, dev->efi_handle);
f725e3
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
f725e3
index 142340372e1..029ee92f5d0 100644
f725e3
--- a/include/grub/efi/api.h
f725e3
+++ b/include/grub/efi/api.h
f725e3
@@ -1564,17 +1564,31 @@ enum
f725e3
     GRUB_EFI_NETWORK_INITIALIZED,
f725e3
   };
f725e3
 
f725e3
+enum
f725e3
+  {
f725e3
+    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST		  = 0x01,
f725e3
+    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST		  = 0x02,
f725e3
+    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST		  = 0x04,
f725e3
+    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS		  = 0x08,
f725e3
+    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
f725e3
+  };
f725e3
+
f725e3
 struct grub_efi_simple_network
f725e3
 {
f725e3
   grub_uint64_t revision;
f725e3
   grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
f725e3
-  void (*stop) (void);
f725e3
+  grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
f725e3
   grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
f725e3
 				   grub_efi_uintn_t extra_rx,
f725e3
 				   grub_efi_uintn_t extra_tx);
f725e3
   void (*reset) (void);
f725e3
-  void (*shutdown) (void);
f725e3
-  void (*receive_filters) (void);
f725e3
+  grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
f725e3
+  grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
f725e3
+					grub_uint32_t enable,
f725e3
+					grub_uint32_t disable,
f725e3
+					grub_efi_boolean_t reset_mcast_filter,
f725e3
+					grub_efi_uintn_t mcast_filter_count,
f725e3
+					grub_efi_mac_address_t *mcast_filter);
f725e3
   void (*station_address) (void);
f725e3
   void (*statistics) (void);
f725e3
   void (*mcastiptomac) (void);