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 <jba...@fb.com> --- 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 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel