From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1aTcWM-0000Qv-DB for mharc-grub-devel@gnu.org; Wed, 10 Feb 2016 16:41:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51896) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTcWJ-0000Pa-8d for grub-devel@gnu.org; Wed, 10 Feb 2016 16:41:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aTcWF-0003Mg-7G for grub-devel@gnu.org; Wed, 10 Feb 2016 16:41:55 -0500 Received: from 66-220-144-178.intmgw.facebook.com ([66.220.144.178]:26164 helo=mx-out.facebook.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTcWF-0003M5-1S for grub-devel@gnu.org; Wed, 10 Feb 2016 16:41:51 -0500 Received: from facebook.com (2401:db00:2040:5012:face:0:9:0) by mx-out.facebook.com (10.103.99.97) with ESMTP id 0d417854d03c11e5917f0002c9931860-e36e9270 for ; Wed, 10 Feb 2016 13:20:04 -0800 Received: by devbig041.ash4.facebook.com (Postfix, from userid 8730) id B8CFB4540BED; Wed, 10 Feb 2016 13:21:10 -0800 (PST) From: Josef Bacik To: grub-devel@gnu.org, kernel-team@fb.com Subject: [PATCH 09/14] efinet: clear the txbuffer before modifying the receive filters Date: Wed, 10 Feb 2016 13:21:03 -0800 Message-Id: <1455139268-3241273-10-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1455139268-3241273-1-git-send-email-jbacik@fb.com> References: <1455139268-3241273-1-git-send-email-jbacik@fb.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 66.220.144.178 Cc: Josef Bacik X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Feb 2016 21:41:56 -0000 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 --- 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