]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[intelxl] Read PCI bus:dev.fn number from PFFUNC_RID register
authorMichael Brown <mcb30@ipxe.org>
Sat, 21 Nov 2020 13:19:27 +0000 (13:19 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 21 Nov 2020 13:35:11 +0000 (13:35 +0000)
For the physical function driver, the transmit queue needs to be
configured to be associated with the relevant physical function
number.  This is currently obtained from the bus:dev.fn address of the
underlying PCI device.

In the case of a virtual machine using the physical function via PCI
passthrough, the PCI bus:dev.fn address within the virtual machine is
unrelated to the real physical function number.  Such a function will
typically be presented to the virtual machine as a single-function
device.  The function number extracted from the PCI bus:dev.fn address
will therefore always be zero.

Fix by reading from the Function Requester ID Information Register,
which always returns the real PCI bus:dev.fn address as used by the
physical host.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/intelxl.c
src/drivers/net/intelxl.h

index fda8effbd0dff4490338da2a65d41b2f976783fe..d929f48cd2a2dd006416810206aecd81150d935f 100644 (file)
@@ -1643,6 +1643,7 @@ static struct net_device_operations intelxl_operations = {
 static int intelxl_probe ( struct pci_device *pci ) {
        struct net_device *netdev;
        struct intelxl_nic *intelxl;
+       uint32_t pffunc_rid;
        uint32_t pfgen_portnum;
        uint32_t pflan_qalloc;
        int rc;
@@ -1658,7 +1659,6 @@ static int intelxl_probe ( struct pci_device *pci ) {
        pci_set_drvdata ( pci, netdev );
        netdev->dev = &pci->dev;
        memset ( intelxl, 0, sizeof ( *intelxl ) );
-       intelxl->pf = PCI_FUNC ( pci->busdevfn );
        intelxl->intr = INTELXL_PFINT_DYN_CTL0;
        intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD,
                             &intelxl_admin_offsets );
@@ -1685,7 +1685,9 @@ static int intelxl_probe ( struct pci_device *pci ) {
        if ( ( rc = intelxl_reset ( intelxl ) ) != 0 )
                goto err_reset;
 
-       /* Get port number and base queue number */
+       /* Get function number, port number and base queue number */
+       pffunc_rid = readl ( intelxl->regs + INTELXL_PFFUNC_RID );
+       intelxl->pf = INTELXL_PFFUNC_RID_FUNC_NUM ( pffunc_rid );
        pfgen_portnum = readl ( intelxl->regs + INTELXL_PFGEN_PORTNUM );
        intelxl->port = INTELXL_PFGEN_PORTNUM_PORT_NUM ( pfgen_portnum );
        pflan_qalloc = readl ( intelxl->regs + INTELXL_PFLAN_QALLOC );
index 2d33ed8e9d6cac2c9f41473ddf08d2e439f93342..ef9152f6e35632b7dfdde0959a99ada01d32df7e 100644 (file)
@@ -985,6 +985,11 @@ intelxl_init_ring ( struct intelxl_ring *ring, unsigned int count, size_t len,
 /** Time to delay for device reset, in milliseconds */
 #define INTELXL_RESET_DELAY_MS 100
 
+/** Function Requester ID Information Register */
+#define INTELXL_PFFUNC_RID 0x09c000
+#define INTELXL_PFFUNC_RID_FUNC_NUM(x) \
+       ( ( (x) >> 0 ) & 0x3 )                          /**< Function number */
+
 /** PF Queue Allocation Register */
 #define INTELXL_PFLAN_QALLOC 0x1c0400
 #define INTELXL_PFLAN_QALLOC_FIRSTQ(x) \