Skip to content

Commit

Permalink
[intelxl] Allow for virtual function admin queue register maps
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Apr 27, 2019
1 parent c901b5c commit c5ccfe7
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 21 deletions.
47 changes: 31 additions & 16 deletions src/drivers/net/intelxl.c
Expand Up @@ -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
*
Expand All @@ -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 */
Expand All @@ -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 ) ),
Expand All @@ -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 ) ) );
Expand All @@ -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;
Expand Down Expand Up @@ -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++ ) {
Expand Down Expand Up @@ -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 );
}

/**
Expand Down Expand Up @@ -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,
Expand Down
33 changes: 28 additions & 5 deletions src/drivers/net/intelxl.h
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
};
Expand All @@ -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 */
Expand Down

0 comments on commit c5ccfe7

Please sign in to comment.