Blame SOURCES/0001-efi-perform-cable-detection-at-NII-initialization-on-HPE-557SFP.patch

bdf3d7
From 2de005e9ac399f7064968a2611f266dc86a96700 Mon Sep 17 00:00:00 2001
bdf3d7
From: Laszlo Ersek <lersek@redhat.com>
bdf3d7
Date: Fri, 24 Jul 2020 19:15:28 +0200
bdf3d7
Subject: [PATCH] [efi] perform cable detection at NII initialization on HPE
bdf3d7
 557SFP+
bdf3d7
bdf3d7
Commit c0b61bad99ba ("[efi] Work around bugs in Emulex NII driver",
bdf3d7
2015-08-17) added PXE_OPFLAGS_INITIALIZE_DETECT_CABLE to nii_open() for
bdf3d7
working around Emulex NII driver bugs.
bdf3d7
bdf3d7
That broke some Mellanox drivers, so commit 6324227dcaa8 ("[efi] Skip
bdf3d7
cable detection at initialisation where possible", 2017-03-19) predicated
bdf3d7
PXE_OPFLAGS_INITIALIZE_DETECT_CABLE on the NII driver's *inability* to
bdf3d7
report link status.
bdf3d7
bdf3d7
This in turn breaks the NII driver on (some?) HPE 557SFP+ cards, as those
bdf3d7
drivers are capable of reporting link status, but they still need cable
bdf3d7
detection.
bdf3d7
bdf3d7
So check for this card (through PCI vendor / device / subsys vendor /
bdf3d7
subsys device identifiers), and opt for cable detection regardless of link
bdf3d7
status reporting.
bdf3d7
bdf3d7
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1740827
bdf3d7
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
bdf3d7
---
bdf3d7
 src/drivers/net/efi/nii.c | 43 ++++++++++++++++++++++++++++++++++++---
bdf3d7
 1 file changed, 40 insertions(+), 3 deletions(-)
bdf3d7
bdf3d7
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
bdf3d7
index 2d87e0c63f14..0cf065e0818f 100644
bdf3d7
--- a/src/drivers/net/efi/nii.c
bdf3d7
+++ b/src/drivers/net/efi/nii.c
bdf3d7
@@ -193,6 +193,9 @@ struct nii_nic {
bdf3d7
 
bdf3d7
 	/** Mapping list */
bdf3d7
 	struct list_head mappings;
bdf3d7
+
bdf3d7
+	/** quirk needed for HPE 557SFP+ */
bdf3d7
+	int quirk_hpe557sfpp;
bdf3d7
 };
bdf3d7
 
bdf3d7
 /** Maximum number of received packets per poll */
bdf3d7
@@ -219,6 +222,7 @@ static int nii_pci_open ( struct nii_nic *nii ) {
bdf3d7
 	int bar;
bdf3d7
 	EFI_STATUS efirc;
bdf3d7
 	int rc;
bdf3d7
+	uint16_t vid, did, subsys_vid, subsys_did;
bdf3d7
 
bdf3d7
 	/* Locate PCI I/O protocol */
bdf3d7
 	if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid,
bdf3d7
@@ -255,7 +259,7 @@ static int nii_pci_open ( struct nii_nic *nii ) {
bdf3d7
 			rc = -EEFI ( efirc );
bdf3d7
 			DBGC ( nii, "NII %s could not get BAR %d attributes: "
bdf3d7
 			       "%s\n", nii->dev.name, bar, strerror ( rc ) );
bdf3d7
-			goto err_get_bar_attributes;
bdf3d7
+			goto err_pci;
bdf3d7
 		}
bdf3d7
 		if ( desc.acpi->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM ) {
bdf3d7
 			nii->mem_bar = bar;
bdf3d7
@@ -276,9 +280,36 @@ static int nii_pci_open ( struct nii_nic *nii ) {
bdf3d7
 		DBGC ( nii, "no I/O BAR\n" );
bdf3d7
 	}
bdf3d7
 
bdf3d7
+	/* Check if HPE 557SFP+ quirk is needed */
bdf3d7
+	if ( ( efirc = nii->pci_io->Pci.Read ( nii->pci_io,
bdf3d7
+					       EfiPciIoWidthUint16,
bdf3d7
+					       PCI_VENDOR_ID, 1,
bdf3d7
+					       &vid ) ) != 0 ||
bdf3d7
+	     ( efirc = nii->pci_io->Pci.Read ( nii->pci_io,
bdf3d7
+					       EfiPciIoWidthUint16,
bdf3d7
+					       PCI_DEVICE_ID, 1,
bdf3d7
+					       &did ) ) != 0 ||
bdf3d7
+	     ( efirc = nii->pci_io->Pci.Read ( nii->pci_io,
bdf3d7
+					       EfiPciIoWidthUint16,
bdf3d7
+					       PCI_SUBSYSTEM_VENDOR_ID, 1,
bdf3d7
+					       &subsys_vid ) ) != 0 ||
bdf3d7
+	     ( efirc = nii->pci_io->Pci.Read ( nii->pci_io,
bdf3d7
+					       EfiPciIoWidthUint16,
bdf3d7
+					       PCI_SUBSYSTEM_ID, 1,
bdf3d7
+					       &subsys_did ) ) != 0 ) {
bdf3d7
+		rc = -EEFI ( efirc );
bdf3d7
+		DBGC ( nii, "NII %s could not read PCI config space: %s\n",
bdf3d7
+		       nii->dev.name, strerror ( rc ) );
bdf3d7
+		goto err_pci;
bdf3d7
+	}
bdf3d7
+
bdf3d7
+	nii->quirk_hpe557sfpp = ( vid == 0x10df &&
bdf3d7
+				  did == 0x0720 &&
bdf3d7
+				  subsys_vid == 0x103c &&
bdf3d7
+				  subsys_did == 0x803f );
bdf3d7
 	return 0;
bdf3d7
 
bdf3d7
- err_get_bar_attributes:
bdf3d7
+ err_pci:
bdf3d7
 	bs->CloseProtocol ( pci_device, &efi_pci_io_protocol_guid,
bdf3d7
 			    efi_image_handle, device );
bdf3d7
  err_open:
bdf3d7
@@ -1144,8 +1175,14 @@ static int nii_open ( struct net_device *netdev ) {
bdf3d7
 	 * cable detection at this point if any only if the driver is
bdf3d7
 	 * not capable of reporting link status changes at runtime via
bdf3d7
 	 * PXE_OPCODE_GET_STATUS.
bdf3d7
+	 *
bdf3d7
+	 * HPE 557SFP+ seems to break with
bdf3d7
+	 * PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE, but works with
bdf3d7
+	 * PXE_OPFLAGS_INITIALIZE_DETECT_CABLE, so ignore link status reporting
bdf3d7
+	 * for that NIC, and always request cable detection.
bdf3d7
 	 */
bdf3d7
-	flags = ( nii->media ? PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
bdf3d7
+	flags = ( ( ! nii->quirk_hpe557sfpp ) && nii->media
bdf3d7
+		  ? PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
bdf3d7
 		  : PXE_OPFLAGS_INITIALIZE_DETECT_CABLE );
bdf3d7
 	if ( ( rc = nii_initialise_flags ( nii, flags ) ) != 0 )
bdf3d7
 		goto err_initialise;
bdf3d7
bdf3d7
base-commit: b76052335788d0ad2c4b0bded116c3b02dd4bbc2
bdf3d7
-- 
bdf3d7
2.19.1.3.g30247aa5d201
bdf3d7