[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 <mcb30@ipxe.org>
pull/92/head
Michael Brown 2019-03-22 15:04:12 +00:00
parent c901b5ca45
commit c5ccfe79cf
2 changed files with 59 additions and 21 deletions

View File

@ -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 * 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, static int intelxl_create_admin ( struct intelxl_nic *intelxl,
struct intelxl_admin *admin ) { struct intelxl_admin *admin ) {
size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC ); 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; physaddr_t address;
/* Allocate admin queue */ /* Allocate admin queue */
@ -147,30 +157,30 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
memset ( admin->desc, 0, len ); memset ( admin->desc, 0, len );
/* Reset head and tail registers */ /* Reset head and tail registers */
writel ( 0, admin_regs + INTELXL_ADMIN_HEAD ); writel ( 0, admin_regs + regs->head );
writel ( 0, admin_regs + INTELXL_ADMIN_TAIL ); writel ( 0, admin_regs + regs->tail );
/* Reset queue index */ /* Reset queue index */
admin->index = 0; admin->index = 0;
/* Program queue address */ /* Program queue address */
address = virt_to_bus ( admin->desc ); 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 ) ) { if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
writel ( ( ( ( uint64_t ) address ) >> 32 ), writel ( ( ( ( uint64_t ) address ) >> 32 ),
admin_regs + INTELXL_ADMIN_BAH ); admin_regs + regs->bah );
} else { } else {
writel ( 0, admin_regs + INTELXL_ADMIN_BAH ); writel ( 0, admin_regs + regs->bah );
} }
/* Program queue length and enable queue */ /* Program queue length and enable queue */
writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) | writel ( ( INTELXL_ADMIN_LEN_LEN ( INTELXL_ADMIN_NUM_DESC ) |
INTELXL_ADMIN_LEN_ENABLE ), INTELXL_ADMIN_LEN_ENABLE ),
admin_regs + INTELXL_ADMIN_LEN ); admin_regs + regs->len );
DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf " DBGC ( intelxl, "INTELXL %p A%cQ is at [%08llx,%08llx) buf "
"[%08llx,%08llx)\n", intelxl, "[%08llx,%08llx)\n", intelxl,
( ( admin->reg == INTELXL_ADMIN_CMD ) ? 'T' : 'R' ), ( ( admin == &intelxl->command ) ? 'T' : 'R' ),
( ( unsigned long long ) address ), ( ( unsigned long long ) address ),
( ( unsigned long long ) address + len ), ( ( unsigned long long ) address + len ),
( ( unsigned long long ) virt_to_bus ( admin->buffer ) ), ( ( 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, static void intelxl_destroy_admin ( struct intelxl_nic *intelxl,
struct intelxl_admin *admin ) { struct intelxl_admin *admin ) {
size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC ); 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 */ /* Disable queue */
writel ( 0, admin_regs + INTELXL_ADMIN_LEN ); writel ( 0, admin_regs + regs->len );
/* Free queue */ /* Free queue */
free_dma ( admin->desc, ( len + sizeof ( *admin->buffer ) ) ); 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, static int intelxl_admin_command ( struct intelxl_nic *intelxl,
struct intelxl_admin_descriptor *cmd ) { struct intelxl_admin_descriptor *cmd ) {
struct intelxl_admin *admin = &intelxl->command; 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; struct intelxl_admin_descriptor *desc;
uint64_t buffer; uint64_t buffer;
unsigned int index; unsigned int index;
@ -245,7 +257,7 @@ static int intelxl_admin_command ( struct intelxl_nic *intelxl,
/* Post command descriptor */ /* Post command descriptor */
wmb(); wmb();
writel ( tail, admin_regs + INTELXL_ADMIN_TAIL ); writel ( tail, admin_regs + regs->tail );
/* Wait for completion */ /* Wait for completion */
for ( i = 0 ; i < INTELXL_ADMIN_MAX_WAIT_MS ; i++ ) { 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 ) { static void intelxl_refill_admin ( struct intelxl_nic *intelxl ) {
struct intelxl_admin *admin = &intelxl->event; 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; unsigned int tail;
/* Update tail pointer */ /* Update tail pointer */
tail = ( ( admin->index + INTELXL_ADMIN_NUM_DESC - 1 ) % tail = ( ( admin->index + INTELXL_ADMIN_NUM_DESC - 1 ) %
INTELXL_ADMIN_NUM_DESC ); 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; netdev->dev = &pci->dev;
memset ( intelxl, 0, sizeof ( *intelxl ) ); memset ( intelxl, 0, sizeof ( *intelxl ) );
intelxl->pf = PCI_FUNC ( pci->busdevfn ); intelxl->pf = PCI_FUNC ( pci->busdevfn );
intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD ); intelxl_init_admin ( &intelxl->command, INTELXL_ADMIN_CMD,
intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT ); &intelxl_admin_offsets );
intelxl_init_admin ( &intelxl->event, INTELXL_ADMIN_EVT,
&intelxl_admin_offsets );
intelxl_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC, intelxl_init_ring ( &intelxl->tx, INTELXL_TX_NUM_DESC,
intelxl_context_tx ); intelxl_context_tx );
intelxl_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC, intelxl_init_ring ( &intelxl->rx, INTELXL_RX_NUM_DESC,

View File

@ -53,6 +53,24 @@ struct intelxl_nic;
/** Admin Queue Tail Register (offset) */ /** Admin Queue Tail Register (offset) */
#define INTELXL_ADMIN_TAIL 0x400 #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 */ /** Admin queue data buffer command parameters */
struct intelxl_admin_buffer_params { struct intelxl_admin_buffer_params {
/** Reserved */ /** Reserved */
@ -343,8 +361,10 @@ struct intelxl_admin {
/** Queue index */ /** Queue index */
unsigned int index; unsigned int index;
/** Register block */ /** Register block base */
unsigned int reg; unsigned int base;
/** Register offsets */
const struct intelxl_admin_offsets *regs;
/** Data buffer */ /** Data buffer */
union intelxl_admin_buffer *buffer; union intelxl_admin_buffer *buffer;
}; };
@ -353,12 +373,15 @@ struct intelxl_admin {
* Initialise admin queue * Initialise admin queue
* *
* @v admin 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 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 */ /** Number of admin queue descriptors */