grub-devel
[Top][All Lists]
Advanced

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

[PATCH 09/14] efinet: clear the txbuffer before modifying the receive fi


From: Josef Bacik
Subject: [PATCH 09/14] efinet: clear the txbuffer before modifying the receive filters
Date: Wed, 10 Feb 2016 13:21:03 -0800

We had some hardware that would hang when trying to modify the receive filters
if there was anything in the tx queue.  So move the common logic out of
send_card_buffer into a new function called clear_txbuffer and then call that
from send_card_buffer and add_addr.  With this patch the buggy firmware now
properly updates the multicast receive filters.  Thanks,

Signed-off-by: Josef Bacik <address@hidden>
---
 grub-core/net/drivers/efi/efinet.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/grub-core/net/drivers/efi/efinet.c 
b/grub-core/net/drivers/efi/efinet.c
index bbbadd2..c1ee18a 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -32,8 +32,7 @@ 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_err_t
-send_card_buffer (struct grub_net_card *dev,
-                 struct grub_net_buff *pack)
+clear_txbuffer (struct grub_net_card *dev)
 {
   grub_efi_status_t st;
   grub_efi_simple_network_t *net = dev->efi_net;
@@ -75,6 +74,21 @@ send_card_buffer (struct grub_net_card *dev,
          return grub_error (GRUB_ERR_TIMEOUT,
                             N_("couldn't send network packet"));
       }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+send_card_buffer (struct grub_net_card *dev,
+                 struct grub_net_buff *pack)
+{
+  grub_efi_status_t st;
+  grub_efi_simple_network_t *net = dev->efi_net;
+  grub_err_t ret;
+  void *txbuf;
+
+  ret = clear_txbuffer (dev);
+  if (ret != GRUB_ERR_NONE)
+    return ret;
 
   dev->last_pkt_size = (pack->tail - pack->data);
   if (dev->last_pkt_size > dev->mtu)
@@ -254,6 +268,7 @@ add_addr (struct grub_net_card *dev,
 {
   grub_efi_simple_network_t *net = dev->efi_net;
   grub_efi_mac_address_t mac_filters[16];
+  grub_uint32_t current_settings = net->mode->receive_filter_setting;
   grub_efi_status_t st;
   unsigned slot = net->mode->mcast_filter_count;
 
@@ -266,11 +281,18 @@ add_addr (struct grub_net_card *dev,
           net->mode->receive_filter_mask))
     return;
 
+  /* Copy the existing filters and add the new filter. */
   grub_memcpy(mac_filters, net->mode->mcast_filter,
              sizeof (grub_efi_mac_address_t) * slot);
   solicited_node_mcast_addr_to_mac (address->ipv6[1], mac_filters[slot++]);
-  st = efi_call_6 (net->receive_filters, net,
-                  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, 0, 0, slot,
+
+  /* Some firmware will hang if we try to modify the receive filters while the
+     tx buffer still has something in the queue, so clear it before resetting
+     the filters. */
+  if (clear_txbuffer (dev) != GRUB_ERR_NONE)
+    grub_dprintf("efinet", "couldn't clear the txbuffer.\n");
+
+  st = efi_call_6 (net->receive_filters, net, current_settings, 0, 0, slot,
                   mac_filters);
   if (st != GRUB_EFI_SUCCESS)
     grub_dprintf("efinet", "failed to add new receive filter %u\n",
-- 
1.8.1




reply via email to

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