From c5ccfe79cf9188c4b4e55370f91c8377808008bb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 22 Mar 2019 15:04:12 +0000 Subject: [intelxl] Allow for virtual function admin queue register maps The register map for the virtual functions appears to have been constructed using a random number generator. Signed-off-by: Michael Brown --- src/drivers/net/intelxl.c | 47 +++++++++++++++++++++++++++++++---------------- src/drivers/net/intelxl.h | 33 ++++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/drivers/net/intelxl.c b/src/drivers/net/intelxl.c index 66221cba..1f0ca2c0 100644 --- a/src/drivers/net/intelxl.c +++ b/src/drivers/net/intelxl.c @@ -123,6 +123,15 @@ static int intelxl_fetch_mac ( struct intelxl_nic *intelxl, ****************************************************************************** */ +/** Admin queue register offsets */ +static const struct intelxl_admin_offsets intelxl_admin_offsets = { + .bal = INTELXL_ADMIN_BAL, + .bah = INTELXL_ADMIN_BAH, + .len = INTELXL_ADMIN_LEN, + .head = INTELXL_ADMIN_HEAD, + .tail = INTELXL_ADMIN_TAIL, +}; + /** * Create admin queue * @@ -133,7 +142,8 @@ static int intelxl_fetch_mac ( struct intelxl_nic *intelxl, static int intelxl_create_admin ( struct intelxl_nic *intelxl, struct intelxl_admin *admin ) { size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC ); - void *admin_regs = ( intelxl->regs + admin->reg ); + const struct intelxl_admin_offsets *regs = admin->regs; + void *admin_regs = ( intelxl->regs + admin->base ); physaddr_t address; /* Allocate admin queue */ @@ -147,30 +157,30 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl, memset ( admin->desc, 0, len ); /* Reset head and tail registers */ - writel ( 0, admin_regs + INTELXL_ADMIN_HEAD ); - writel ( 0, admin_regs + INTELXL_ADMIN_TAIL ); + writel ( 0, admin_regs + regs->head ); + writel ( 0, admin_regs + regs->tail ); /* Reset queue index */ admin->index = 0; /* Program queue address */ address = virt_to_bus ( admin->desc ); - writel ( ( address & 0xffffffffUL ), admin_regs + INTELXL_ADMIN_BAL ); + writel ( ( address & 0xffffffffUL ), admin_regs + regs->bal ); if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) { writel ( ( ( ( uint64_t ) address ) >> 32 ), - admin_regs + INTELXL_ADMIN_BAH ); + admin_regs + regs->bah ); } else { - writel ( 0, admin_regs + INTELXL_ADMIN_BAH ); + writel ( 0, admin_regs + regs->bah ); } /* Program queue length and enable queue */ writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) | INTELXL_ADMIN_LEN_ENABLE ), - admin_regs + INTELXL_ADMIN_LEN ); + admin_regs + regs->len ); DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf " "[%08llx,%08llx)\n", intelxl, - ( ( admin->reg == INTELXL_ADMIN_CMD ) ? 'T' : 'R' ), + ( ( admin == &intelxl->command ) ? 'T' : 'R' ), ( ( unsigned long long ) address ), ( ( unsigned long long ) address + len ), ( ( unsigned long long ) virt_to_bus ( admin->buffer ) ), @@ -188,10 +198,11 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl, static void intelxl_destroy_admin ( struct intelxl_nic *intelxl, struct intelxl_admin *admin ) { size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC ); - void *admin_regs = ( intelxl->regs + admin->reg ); + const struct intelxl_admin_offsets *regs = admin->regs; + void *admin_regs = ( intelxl->regs + admin->base ); /* Disable queue */ - writel ( 0, admin_regs + INTELXL_ADMIN_LEN ); + writel ( 0, admin_regs + regs->len ); /* Free queue */ free_dma ( admin->desc, ( len + sizeof ( *admin->buffer ) ) ); @@ -207,7 +218,8 @@ static void intelxl_destroy_admin ( struct intelxl_nic *intelxl, static int intelxl_admin_command ( struct intelxl_nic *intelxl, struct intelxl_admin_descriptor *cmd ) { struct intelxl_admin *admin = &intelxl->command; - void *admin_regs = ( intelxl->regs + admin->reg ); + const struct intelxl_admin_offsets *regs = admin->regs; + void *admin_regs = ( intelxl->regs + admin->base ); struct intelxl_admin_descriptor *desc; uint64_t buffer; unsigned int index; @@ -245,7 +257,7 @@ static int intelxl_admin_command ( struct intelxl_nic *intelxl, /* Post command descriptor */ wmb(); - writel ( tail, admin_regs + INTELXL_ADMIN_TAIL ); + writel ( tail, admin_regs + regs->tail ); /* Wait for completion */ for ( i = 0 ; i < INTELXL_ADMIN_MAX_WAIT_MS ; i++ ) { @@ -558,13 +570,14 @@ static int intelxl_admin_link ( struct net_device *netdev ) { */ static void intelxl_refill_admin ( struct intelxl_nic *intelxl ) { struct intelxl_admin *admin = &intelxl->event; - void *admin_regs = ( intelxl->regs + admin->reg ); + const struct intelxl_admin_offsets *regs = admin->regs; + void *admin_regs = ( intelxl->regs + admin->base ); unsigned int tail; /* Update tail pointer */ tail = ( ( admin->index + INTELXL_ADMIN_NUM_DESC - 1 ) % INTELXL_ADMIN_NUM_DESC ); - writel ( tail, admin_regs + INTELXL_ADMIN_TAIL ); + writel ( tail, admin_regs + regs->tail ); } /** @@ -1383,8 +1396,10 @@ static int intelxl_probe ( struct pci_device *pci ) { netdev->dev = &pci->dev; memset ( intelxl, 0, sizeof ( *intelxl ) ); intelxl->pf = PCI_FUNC ( pci->busdevfn ); - intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD ); - intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT ); + intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD, + &intelxl_admin_offsets ); + intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT, + &intelxl_admin_offsets ); intelxl_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC, intelxl_context_tx ); intelxl_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC, diff --git a/src/drivers/net/intelxl.h b/src/drivers/net/intelxl.h index fd3fc75b..138fc2ef 100644 --- a/src/drivers/net/intelxl.h +++ b/src/drivers/net/intelxl.h @@ -53,6 +53,24 @@ struct intelxl_nic; /** Admin Queue Tail Register (offset) */ #define INTELXL_ADMIN_TAIL 0x400 +/** Admin queue register offsets + * + * The physical and virtual function register maps have no discernible + * relationship. + */ +struct intelxl_admin_offsets { + /** Base Address Low Register offset */ + unsigned int bal; + /** Base Address High Register offset */ + unsigned int bah; + /** Length Register offset */ + unsigned int len; + /** Head Register offset */ + unsigned int head; + /** Tail Register offset */ + unsigned int tail; +}; + /** Admin queue data buffer command parameters */ struct intelxl_admin_buffer_params { /** Reserved */ @@ -343,8 +361,10 @@ struct intelxl_admin { /** Queue index */ unsigned int index; - /** Register block */ - unsigned int reg; + /** Register block base */ + unsigned int base; + /** Register offsets */ + const struct intelxl_admin_offsets *regs; /** Data buffer */ union intelxl_admin_buffer *buffer; }; @@ -353,12 +373,15 @@ struct intelxl_admin { * Initialise admin queue * * @v admin Admin queue - * @v reg Register block + * @v base Register block base + * @v regs Register offsets */ static inline __attribute__ (( always_inline )) void -intelxl_init_admin ( struct intelxl_admin *admin, unsigned int reg ) { +intelxl_init_admin ( struct intelxl_admin *admin, unsigned int base, + const struct intelxl_admin_offsets *regs ) { - admin->reg = reg; + admin->base = base; + admin->regs = regs; } /** Number of admin queue descriptors */ -- cgit v1.2.3-55-g7522