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

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