From 76a7bfe939b4b6ea88690e8c6960c65d57c01b5e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 21 Nov 2020 13:19:27 +0000 Subject: [PATCH] [intelxl] Read PCI bus:dev.fn number from PFFUNC_RID register 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 --- src/drivers/net/intelxl.c | 6 ++++-- src/drivers/net/intelxl.h | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/drivers/net/intelxl.c b/src/drivers/net/intelxl.c index fda8effbd..d929f48cd 100644 --- a/src/drivers/net/intelxl.c +++ b/src/drivers/net/intelxl.c @@ -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 ); diff --git a/src/drivers/net/intelxl.h b/src/drivers/net/intelxl.h index 2d33ed8e9..ef9152f6e 100644 --- a/src/drivers/net/intelxl.h +++ b/src/drivers/net/intelxl.h @@ -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) \