[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] efinet: clear the txbuffer before modifying the receive filters
From: |
Josef Bacik |
Subject: |
[PATCH] efinet: clear the txbuffer before modifying the receive filters |
Date: |
Wed, 3 Feb 2016 09:02:37 -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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] efinet: clear the txbuffer before modifying the receive filters,
Josef Bacik <=