Please try the patch currently used in Solaris flavour of GRUB. I think of upstreaming their mnp driver Le 13 nov. 2015 3:30 PM, "Josef Bacik" <jba...@fb.com> a écrit :
> On 11/13/2015 08:10 AM, Andrei Borzenkov wrote: > >> On Fri, Nov 13, 2015 at 1:07 AM, Josef Bacik <jba...@fb.com> wrote: >> >>> The firmware bug I've been tracking down has been too extensive to work >>> around >>> effectively. Basically once we switch to EXCLUSIVE everything is >>> completely >>> horked. I can add a multicast filter but it's timing sensitive, so it >>> has to be >>> done at least 10 seconds after initialization for it to take place, and >>> we have >>> to continue to enable PROMISCUOUS_MULTICAST because otherwise we no >>> longer get >>> unicast traffic. I discovered however that if we do not make the >>> EXCLUSIVE >>> switch over everything works fine. So instead add a function that >>> checks for >>> >> >> Does your firmware use MNP at all? >> >> > I was going to look into that today, with as much problems as SNP has been > giving us I'm wondering if MNP works better. I'm going to rig up a > barebones MNP driver and see if it behaves better. The question is how to > make us use MNP vs. SNP when it is supported, or to force us to go back to > SNP if MNP is fuuuuucked up. > > this broken firmware and uses GET_PROTOCOL instead of EXCLUSIVE. This also >>> keeps the original protocol we use when scanning the cards and leaves the >>> initialization stuff for ->open. Thanks, >>> >>> Signed-off-by: Josef Bacik <jba...@fb.com> >>> --- >>> grub-core/net/drivers/efi/efinet.c | 99 >>> ++++++++++++++++++-------------------- >>> 1 file changed, 46 insertions(+), 53 deletions(-) >>> >>> diff --git a/grub-core/net/drivers/efi/efinet.c >>> b/grub-core/net/drivers/efi/efinet.c >>> index c8f80a1..5a207fd 100644 >>> --- a/grub-core/net/drivers/efi/efinet.c >>> +++ b/grub-core/net/drivers/efi/efinet.c >>> @@ -156,59 +156,40 @@ get_card_packet (struct grub_net_card *dev) >>> static grub_err_t >>> open_card (struct grub_net_card *dev) >>> { >>> - grub_efi_simple_network_t *net; >>> + grub_efi_simple_network_t *net = dev->efi_net; >>> >>> - /* Try to reopen SNP exlusively to close any active MNP protocol >>> instance >>> - that may compete for packet polling >>> - */ >>> - net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid, >>> - GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE); >>> - if (net) >>> + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) >>> + return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped", >>> + dev->name); >>> + >>> + if (net->mode->state == GRUB_EFI_NETWORK_STARTED >>> + && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) >>> + return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize >>> failed", >>> + dev->name); >>> + >>> + /* Enable hardware receive filters if driver declares support for it. >>> + We need unicast and broadcast and additionaly all nodes and >>> + solicited multicast for IPv6. Solicited multicast is per-IPv6 >>> + address and we currently do not have API to do it so simply >>> + try to enable receive of all multicast packets or evertyhing in >>> + the worst case (i386 PXE driver always enables promiscuous too). >>> + >>> + This does trust firmware to do what it claims to do. >>> + */ >>> + if (net->mode->receive_filter_mask) >>> { >>> - if (net->mode->state == GRUB_EFI_NETWORK_STOPPED >>> - && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) >>> - return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net start failed", >>> - dev->name); >>> - >>> - if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) >>> - return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped", >>> - dev->name); >>> - >>> - if (net->mode->state == GRUB_EFI_NETWORK_STARTED >>> - && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) >>> - return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize >>> failed", >>> - dev->name); >>> - >>> - /* Enable hardware receive filters if driver declares support for >>> it. >>> - We need unicast and broadcast and additionaly all nodes and >>> - solicited multicast for IPv6. Solicited multicast is per-IPv6 >>> - address and we currently do not have API to do it so simply >>> - try to enable receive of all multicast packets or evertyhing in >>> - the worst case (i386 PXE driver always enables promiscuous too). >>> - >>> - This does trust firmware to do what it claims to do. >>> - */ >>> - if (net->mode->receive_filter_mask) >>> - { >>> - grub_uint32_t filters = >>> GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | >>> - >>> GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | >>> - >>> GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; >>> - >>> - filters &= net->mode->receive_filter_mask; >>> - if (!(filters & >>> GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST)) >>> - filters |= (net->mode->receive_filter_mask & >>> - GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS); >>> + grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST >>> | >>> + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | >>> + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; >>> >>> - efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL); >>> - } >>> + filters &= net->mode->receive_filter_mask; >>> + if (!(filters & >>> GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST)) >>> + filters |= (net->mode->receive_filter_mask & >>> + GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS); >>> >>> - efi_call_4 (grub_efi_system_table->boot_services->close_protocol, >>> - dev->efi_net, &net_io_guid, >>> - grub_efi_image_handle, dev->efi_handle); >>> - dev->efi_net = net; >>> + efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL); >>> } >>> >>> - /* If it failed we just try to run as best as we can */ >>> return GRUB_ERR_NONE; >>> } >>> >>> @@ -278,12 +259,26 @@ grub_efinet_is_mac_device (struct grub_net_card >>> *card) >>> return 0; >>> } >>> >>> +static grub_efi_uint32_t >>> +grub_snp_attributes (void) >>> >> >> Attributes? I'd say >> >> use_snp ? GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE : >> GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> looks more readable. >> >> +{ >>> + /* Some firmware will completely screw up the transition to exclusive >>> SNP, >>> + doing things like not honoring receive filters or taking multiple >>> seconds >>> + to make the switch over. So don't bother using exclusive in this >>> case. >>> + */ >>> + if (!grub_memcmp(grub_efi_system_table->firmware_vendor, "A", 1) && >>> + grub_efi_system_table->firmware_revision == >>> (grub_efi_uint32_t)262798) >>> >> >> Well, I'm not thrilled by this check ... at least we need to compare >> full firmware_vendor then. >> >> > That is the full firmware_vendor for our firmware. I suppose I should > also do strlen(firmware_vendor) == 1 && memcmp() to make sure it doesn't > just match something that starts with A, I can fix that up. > > + return GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL; >>> + return GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE; >>> +} >>> + >>> static void >>> grub_efinet_findcards (void) >>> { >>> grub_efi_uintn_t num_handles; >>> grub_efi_handle_t *handles; >>> grub_efi_handle_t *handle; >>> + grub_efi_uint32_t attributes; >>> int i = 0; >>> >>> /* Find handles which support the disk io interface. */ >>> @@ -291,6 +286,9 @@ grub_efinet_findcards (void) >>> 0, &num_handles); >>> if (! handles) >>> return; >>> + >>> + attributes = grub_snp_attributes(); >>> + >>> for (handle = handles; num_handles--; handle++) >>> { >>> grub_efi_simple_network_t *net; >>> @@ -319,8 +317,7 @@ grub_efinet_findcards (void) >>> && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == >>> GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE) >>> continue; >>> >>> - net = grub_efi_open_protocol (*handle, &net_io_guid, >>> - GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); >>> + net = grub_efi_open_protocol (*handle, &net_io_guid, attributes); >>> >> >> No, we cannot open exclusively here, it will destroy autocnfiguration >> information we need later. You need to add conditional in open_card. >> > > The autoconfig stuff still works later for me but I can change it back. > Thanks, > > Josef > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel >
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel