I have an Intel 82599 10 gigabit ethernet card I wanted to get working
on my SiFive Unmatched board.

I found the ix(4) driver has some weirdness around MSI-X
interrupts. While the driver supports operating both with and without
MSI-X support, it's hard-coded via a flag rather than dynamically checking
if it's available. If the flag is set (which it always is right now),
but MSI-X isn't available, the driver will throw an error and the device
won't work:

ix0 at pci7 dev 0 function 0 "Intel 82599" rev 0x01ixgbe_allocate_msix: 
pci_intr_map_msix vec 0 failed

The root cause is this call failing in if_ix.c:

                if (pci_intr_map_msix(pa, i, &ih)) {
                        printf("ixgbe_allocate_msix: "
                            "pci_intr_map_msix vec %d failed\n", i);
                        error = ENOMEM;
                        goto fail;
                }


Because in _pci_intr_map_msix (in sys/arch/riscv64/dev/pci_machdep.c):

if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 ||
            pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0)
                return -1;

The PCI attach flags would not have PCI_FLAGS_MSI_ENABLED set.

The following diff remedies that by checking if PCI_FLAGS_MSI_ENABLED is
actually set, rather than just trying and failing because the hard-coded
flag says so. It also enables ix(4) in the kernel config for
riscv64. Effectively, the driver will now only try to use MSI-X if the
machine is advertising it to be available.

I've tested this on riscv64 (obviously) and an amd64 machine with the
same model card.

On riscv64 the device shows up as:

ix0 at pci7 dev 0 function 0 "Intel 82599" rev 0x01: intx, address 
90:e2:ba:29:18:72

And seems to be happily passing packets.

On amd64, the device still shows up as using MSI-X as it did before:

ix0 at pci2 dev 0 function 0 "Intel 82599" rev 0x01, msix, 8 queues,
address 90:e2:ba:29:76:a0

I notice in some of the other drivers for Intel ethernet chipsets, this
same flag exists. I don't know if it's preferable to make this same
change to them nor do I have the hardware to test such a change, but if
this is something that's of interest I'd be happy to do it.

Thanks!

Index: sys/arch/riscv64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/riscv64/conf/GENERIC,v
retrieving revision 1.26
diff -u -p -u -p -r1.26 GENERIC
--- sys/arch/riscv64/conf/GENERIC	12 Jul 2021 19:11:42 -0000	1.26
+++ sys/arch/riscv64/conf/GENERIC	19 Jul 2021 22:53:38 -0000
@@ -94,6 +94,7 @@ wsdisplay*	at radeondrm?
 em*		at pci?		# Intel Pro/1000 Ethernet
 bge*		at pci?		# Broadcom BCM57xx (aka Tigon3)
 oce*		at pci?		# Emulex OneConnect 10Gb ethernet
+ix*		at pci?		# Intel 82598EB 10Gb ethernet
 
 nvme*		at pci?		# NVMe controllers
 ahci*		at pci?		# AHCI SATA controllers
Index: sys/dev/pci/if_ix.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ix.c,v
retrieving revision 1.178
diff -u -p -u -p -r1.178 if_ix.c
--- sys/dev/pci/if_ix.c	22 Dec 2020 23:25:37 -0000	1.178
+++ sys/dev/pci/if_ix.c	19 Jul 2021 22:53:38 -0000
@@ -202,7 +202,6 @@ struct cfattach ix_ca = {
 };
 
 int ixgbe_smart_speed = ixgbe_smart_speed_on;
-int ixgbe_enable_msix = 1;
 
 /*********************************************************************
  *  Device identification routine
@@ -1780,7 +1779,7 @@ ixgbe_setup_msix(struct ix_softc *sc)
 	int			 nmsix;
 	unsigned int		 maxq;
 
-	if (!ixgbe_enable_msix)
+	if (!(pa->pa_flags & PCI_FLAGS_MSI_ENABLED))
 		return;
 
 	nmsix = pci_intr_msix_count(pa->pa_pc, pa->pa_tag);

Reply via email to