summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2019-04-24 13:18:12 +0200
committerMichael Brown2019-04-27 21:25:59 +0200
commit8f3e648b6ce2b14940b8eb30efab3cb05820ca8a (patch)
tree09a5a4bef6f000631c221a5181064cae37c98da7
parent[intelxl] Allow for virtual function admin queue register maps (diff)
downloadipxe-8f3e648b6ce2b14940b8eb30efab3cb05820ca8a.tar.gz
ipxe-8f3e648b6ce2b14940b8eb30efab3cb05820ca8a.tar.xz
ipxe-8f3e648b6ce2b14940b8eb30efab3cb05820ca8a.zip
[intelxl] Use one admin queue buffer per admin queue descriptor
We currently use a single data buffer shared between all admin queue descriptors. This works for the physical function driver since we have at most one command in progress and only a single event (which does not use a data buffer). The communication path between the physical and virtual function drivers uses the event data buffer, and there is no way to prevent a solicited event (i.e. a response to a request) from being overwritten by an unsolicited event (e.g. a link status change). Provide individual data buffers for each admin event queue descriptor (and for each admin command queue descriptor, for the sake of consistency). Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/drivers/net/intelxl.c309
-rw-r--r--src/drivers/net/intelxl.h6
2 files changed, 197 insertions, 118 deletions
diff --git a/src/drivers/net/intelxl.c b/src/drivers/net/intelxl.c
index 1f0ca2c0..c0fb4c24 100644
--- a/src/drivers/net/intelxl.c
+++ b/src/drivers/net/intelxl.c
@@ -141,17 +141,17 @@ static const struct intelxl_admin_offsets intelxl_admin_offsets = {
*/
static int intelxl_create_admin ( struct intelxl_nic *intelxl,
struct intelxl_admin *admin ) {
+ size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
const struct intelxl_admin_offsets *regs = admin->regs;
void *admin_regs = ( intelxl->regs + admin->base );
physaddr_t address;
/* Allocate admin queue */
- admin->desc = malloc_dma ( ( len + sizeof ( *admin->buffer ) ),
- INTELXL_ALIGN );
- if ( ! admin->desc )
+ admin->buf = malloc_dma ( ( buf_len + len ), INTELXL_ALIGN );
+ if ( ! admin->buf )
return -ENOMEM;
- admin->buffer = ( ( ( void * ) admin->desc ) + len );
+ admin->desc = ( ( ( void * ) admin->buf ) + buf_len );
/* Initialise admin queue */
memset ( admin->desc, 0, len );
@@ -183,9 +183,9 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
( ( admin == &intelxl->command ) ? 'T' : 'R' ),
( ( unsigned long long ) address ),
( ( unsigned long long ) address + len ),
- ( ( unsigned long long ) virt_to_bus ( admin->buffer ) ),
- ( ( unsigned long long ) ( virt_to_bus ( admin->buffer ) +
- sizeof ( admin->buffer[0] ) ) ) );
+ ( ( unsigned long long ) virt_to_bus ( admin->buf ) ),
+ ( ( unsigned long long ) ( virt_to_bus ( admin->buf ) +
+ buf_len ) ) );
return 0;
}
@@ -197,6 +197,7 @@ static int intelxl_create_admin ( struct intelxl_nic *intelxl,
*/
static void intelxl_destroy_admin ( struct intelxl_nic *intelxl,
struct intelxl_admin *admin ) {
+ size_t buf_len = ( sizeof ( admin->buf[0] ) * INTELXL_ADMIN_NUM_DESC );
size_t len = ( sizeof ( admin->desc[0] ) * INTELXL_ADMIN_NUM_DESC );
const struct intelxl_admin_offsets *regs = admin->regs;
void *admin_regs = ( intelxl->regs + admin->base );
@@ -205,23 +206,80 @@ static void intelxl_destroy_admin ( struct intelxl_nic *intelxl,
writel ( 0, admin_regs + regs->len );
/* Free queue */
- free_dma ( admin->desc, ( len + sizeof ( *admin->buffer ) ) );
+ free_dma ( admin->buf, ( buf_len + len ) );
+}
+
+/**
+ * Get next admin command queue descriptor
+ *
+ * @v intelxl Intel device
+ * @ret cmd Command descriptor
+ */
+static struct intelxl_admin_descriptor *
+intelxl_admin_command_descriptor ( struct intelxl_nic *intelxl ) {
+ struct intelxl_admin *admin = &intelxl->command;
+ struct intelxl_admin_descriptor *cmd;
+
+ /* Get and initialise next descriptor */
+ cmd = &admin->desc[ admin->index % INTELXL_ADMIN_NUM_DESC ];
+ memset ( cmd, 0, sizeof ( *cmd ) );
+ return cmd;
+}
+
+/**
+ * Get next admin command queue data buffer
+ *
+ * @v intelxl Intel device
+ * @ret buf Data buffer
+ */
+static union intelxl_admin_buffer *
+intelxl_admin_command_buffer ( struct intelxl_nic *intelxl ) {
+ struct intelxl_admin *admin = &intelxl->command;
+ union intelxl_admin_buffer *buf;
+
+ /* Get next data buffer */
+ buf = &admin->buf[ admin->index % INTELXL_ADMIN_NUM_DESC ];
+ memset ( buf, 0, sizeof ( *buf ) );
+ return buf;
+}
+
+/**
+ * Initialise admin event queue descriptor
+ *
+ * @v intelxl Intel device
+ * @v index Event queue index
+ */
+static void intelxl_admin_event_init ( struct intelxl_nic *intelxl,
+ unsigned int index ) {
+ struct intelxl_admin *admin = &intelxl->event;
+ struct intelxl_admin_descriptor *evt;
+ union intelxl_admin_buffer *buf;
+ uint64_t address;
+
+ /* Initialise descriptor */
+ evt = &admin->desc[ index % INTELXL_ADMIN_NUM_DESC ];
+ buf = &admin->buf[ index % INTELXL_ADMIN_NUM_DESC ];
+ address = virt_to_bus ( buf );
+ evt->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
+ evt->len = cpu_to_le16 ( sizeof ( *buf ) );
+ evt->params.buffer.high = cpu_to_le32 ( address >> 32 );
+ evt->params.buffer.low = cpu_to_le32 ( address & 0xffffffffUL );
}
/**
* Issue admin queue command
*
* @v intelxl Intel device
- * @v cmd Command descriptor
* @ret rc Return status code
*/
-static int intelxl_admin_command ( struct intelxl_nic *intelxl,
- struct intelxl_admin_descriptor *cmd ) {
+static int intelxl_admin_command ( struct intelxl_nic *intelxl ) {
struct intelxl_admin *admin = &intelxl->command;
const struct intelxl_admin_offsets *regs = admin->regs;
void *admin_regs = ( intelxl->regs + admin->base );
- struct intelxl_admin_descriptor *desc;
- uint64_t buffer;
+ struct intelxl_admin_descriptor *cmd;
+ union intelxl_admin_buffer *buf;
+ uint64_t address;
+ uint32_t cookie;
unsigned int index;
unsigned int tail;
unsigned int i;
@@ -230,32 +288,36 @@ static int intelxl_admin_command ( struct intelxl_nic *intelxl,
/* Get next queue entry */
index = admin->index++;
tail = ( admin->index % INTELXL_ADMIN_NUM_DESC );
- desc = &admin->desc[index % INTELXL_ADMIN_NUM_DESC];
-
- /* Clear must-be-zero flags */
- cmd->flags &= ~cpu_to_le16 ( INTELXL_ADMIN_FL_DD |
- INTELXL_ADMIN_FL_CMP |
- INTELXL_ADMIN_FL_ERR );
-
- /* Clear return value */
- cmd->ret = 0;
+ cmd = &admin->desc[ index % INTELXL_ADMIN_NUM_DESC ];
+ buf = &admin->buf[ index % INTELXL_ADMIN_NUM_DESC ];
+ DBGC2 ( intelxl, "INTELXL %p admin command %#x opcode %#04x:\n",
+ intelxl, index, le16_to_cpu ( cmd->opcode ) );
- /* Populate cookie */
- cmd->cookie = cpu_to_le32 ( index );
+ /* Sanity checks */
+ assert ( ! ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_DD ) ) );
+ assert ( ! ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_CMP ) ) );
+ assert ( ! ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_ERR ) ) );
+ assert ( cmd->ret == 0 );
/* Populate data buffer address if applicable */
if ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
- buffer = virt_to_bus ( admin->buffer );
- cmd->params.buffer.high = cpu_to_le32 ( buffer >> 32 );
- cmd->params.buffer.low = cpu_to_le32 ( buffer & 0xffffffffUL );
+ address = virt_to_bus ( buf );
+ cmd->params.buffer.high = cpu_to_le32 ( address >> 32 );
+ cmd->params.buffer.low = cpu_to_le32 ( address & 0xffffffffUL );
}
- /* Copy command descriptor to queue entry */
- memcpy ( desc, cmd, sizeof ( *desc ) );
- DBGC2 ( intelxl, "INTELXL %p admin command %#x:\n", intelxl, index );
- DBGC2_HDA ( intelxl, virt_to_phys ( desc ), desc, sizeof ( *desc ) );
+ /* Populate cookie */
+ cmd->cookie = cpu_to_le32 ( index );
+
+ /* Record cookie */
+ cookie = cmd->cookie;
/* Post command descriptor */
+ DBGC2_HDA ( intelxl, virt_to_phys ( cmd ), cmd, sizeof ( *cmd ) );
+ if ( cmd->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
+ DBGC2_HDA ( intelxl, virt_to_phys ( buf ), buf,
+ le16_to_cpu ( cmd->len ) );
+ }
wmb();
writel ( tail, admin_regs + regs->tail );
@@ -263,36 +325,33 @@ static int intelxl_admin_command ( struct intelxl_nic *intelxl,
for ( i = 0 ; i < INTELXL_ADMIN_MAX_WAIT_MS ; i++ ) {
/* If response is not complete, delay 1ms and retry */
- if ( ! ( desc->flags & INTELXL_ADMIN_FL_DD ) ) {
+ if ( ! ( cmd->flags & INTELXL_ADMIN_FL_DD ) ) {
mdelay ( 1 );
continue;
}
DBGC2 ( intelxl, "INTELXL %p admin command %#x response:\n",
intelxl, index );
- DBGC2_HDA ( intelxl, virt_to_phys ( desc ), desc,
- sizeof ( *desc ) );
+ DBGC2_HDA ( intelxl, virt_to_phys ( cmd ), cmd,
+ sizeof ( *cmd ) );
/* Check for cookie mismatch */
- if ( desc->cookie != cmd->cookie ) {
+ if ( cmd->cookie != cookie ) {
DBGC ( intelxl, "INTELXL %p admin command %#x bad "
"cookie %#x\n", intelxl, index,
- le32_to_cpu ( desc->cookie ) );
+ le32_to_cpu ( cmd->cookie ) );
rc = -EPROTO;
goto err;
}
/* Check for errors */
- if ( desc->ret != 0 ) {
+ if ( cmd->ret != 0 ) {
DBGC ( intelxl, "INTELXL %p admin command %#x error "
"%d\n", intelxl, index,
- le16_to_cpu ( desc->ret ) );
+ le16_to_cpu ( cmd->ret ) );
rc = -EIO;
goto err;
}
- /* Copy response back to command descriptor */
- memcpy ( cmd, desc, sizeof ( *cmd ) );
-
/* Success */
return 0;
}
@@ -301,8 +360,7 @@ static int intelxl_admin_command ( struct intelxl_nic *intelxl,
DBGC ( intelxl, "INTELXL %p timed out waiting for admin command %#x:\n",
intelxl, index );
err:
- DBGC_HDA ( intelxl, virt_to_phys ( desc ), cmd, sizeof ( *cmd ) );
- DBGC_HDA ( intelxl, virt_to_phys ( desc ), desc, sizeof ( *desc ) );
+ DBGC_HDA ( intelxl, virt_to_phys ( cmd ), cmd, sizeof ( *cmd ) );
return rc;
}
@@ -313,17 +371,18 @@ static int intelxl_admin_command ( struct intelxl_nic *intelxl,
* @ret rc Return status code
*/
static int intelxl_admin_version ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_version_params *version = &cmd.params.version;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_version_params *version;
unsigned int api;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_VERSION );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_VERSION );
+ version = &cmd->params.version;
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
api = le16_to_cpu ( version->api.major );
DBGC ( intelxl, "INTELXL %p firmware v%d.%d API v%d.%d\n",
@@ -348,24 +407,25 @@ static int intelxl_admin_version ( struct intelxl_nic *intelxl ) {
* @ret rc Return status code
*/
static int intelxl_admin_driver ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_driver_params *driver = &cmd.params.driver;
- struct intelxl_admin_driver_buffer *buf =
- &intelxl->command.buffer->driver;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_driver_params *driver;
+ union intelxl_admin_buffer *buf;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_DRIVER );
- cmd.flags = cpu_to_le16 ( INTELXL_ADMIN_FL_RD | INTELXL_ADMIN_FL_BUF );
- cmd.len = cpu_to_le16 ( sizeof ( *buf ) );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_DRIVER );
+ cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_RD | INTELXL_ADMIN_FL_BUF );
+ cmd->len = cpu_to_le16 ( sizeof ( buf->driver ) );
+ driver = &cmd->params.driver;
driver->major = product_major_version;
driver->minor = product_minor_version;
- snprintf ( buf->name, sizeof ( buf->name ), "%s",
+ buf = intelxl_admin_command_buffer ( intelxl );
+ snprintf ( buf->driver.name, sizeof ( buf->driver.name ), "%s",
( product_name[0] ? product_name : product_short_name ) );
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
return 0;
@@ -378,17 +438,18 @@ static int intelxl_admin_driver ( struct intelxl_nic *intelxl ) {
* @ret rc Return status code
*/
static int intelxl_admin_shutdown ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_shutdown_params *shutdown = &cmd.params.shutdown;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_shutdown_params *shutdown;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_SHUTDOWN );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_SHUTDOWN );
+ shutdown = &cmd->params.shutdown;
shutdown->unloading = INTELXL_ADMIN_SHUTDOWN_UNLOADING;
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
return 0;
@@ -401,36 +462,38 @@ static int intelxl_admin_shutdown ( struct intelxl_nic *intelxl ) {
* @ret rc Return status code
*/
static int intelxl_admin_switch ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_switch_params *sw = &cmd.params.sw;
- struct intelxl_admin_switch_buffer *buf = &intelxl->command.buffer->sw;
- struct intelxl_admin_switch_config *cfg = &buf->cfg;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_switch_params *sw;
+ union intelxl_admin_buffer *buf;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_SWITCH );
- cmd.flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
- cmd.len = cpu_to_le16 ( sizeof ( *buf ) );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_SWITCH );
+ cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
+ cmd->len = cpu_to_le16 ( sizeof ( buf->sw ) );
+ sw = &cmd->params.sw;
+ buf = intelxl_admin_command_buffer ( intelxl );
/* Get each configuration in turn */
do {
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
/* Dump raw configuration */
DBGC2 ( intelxl, "INTELXL %p SEID %#04x:\n",
- intelxl, le16_to_cpu ( cfg->seid ) );
- DBGC2_HDA ( intelxl, 0, cfg, sizeof ( *cfg ) );
+ intelxl, le16_to_cpu ( buf->sw.cfg.seid ) );
+ DBGC2_HDA ( intelxl, 0, &buf->sw.cfg, sizeof ( buf->sw.cfg ) );
/* Parse response */
- if ( cfg->type == INTELXL_ADMIN_SWITCH_TYPE_VSI ) {
- intelxl->vsi = le16_to_cpu ( cfg->seid );
+ if ( buf->sw.cfg.type == INTELXL_ADMIN_SWITCH_TYPE_VSI ) {
+ intelxl->vsi = le16_to_cpu ( buf->sw.cfg.seid );
DBGC ( intelxl, "INTELXL %p VSI %#04x uplink %#04x "
"downlink %#04x conn %#02x\n", intelxl,
- intelxl->vsi, le16_to_cpu ( cfg->uplink ),
- le16_to_cpu ( cfg->downlink ), cfg->connection );
+ intelxl->vsi, le16_to_cpu ( buf->sw.cfg.uplink ),
+ le16_to_cpu ( buf->sw.cfg.downlink ),
+ buf->sw.cfg.connection );
}
} while ( sw->next );
@@ -451,25 +514,27 @@ static int intelxl_admin_switch ( struct intelxl_nic *intelxl ) {
* @ret rc Return status code
*/
static int intelxl_admin_vsi ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_vsi_params *vsi = &cmd.params.vsi;
- struct intelxl_admin_vsi_buffer *buf = &intelxl->command.buffer->vsi;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_vsi_params *vsi;
+ union intelxl_admin_buffer *buf;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_VSI );
- cmd.flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
- cmd.len = cpu_to_le16 ( sizeof ( *buf ) );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_VSI );
+ cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_BUF );
+ cmd->len = cpu_to_le16 ( sizeof ( buf->vsi ) );
+ vsi = &cmd->params.vsi;
vsi->vsi = cpu_to_le16 ( intelxl->vsi );
+ buf = intelxl_admin_command_buffer ( intelxl );
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
/* Parse response */
- intelxl->queue = le16_to_cpu ( buf->queue[0] );
- intelxl->qset = le16_to_cpu ( buf->qset[0] );
+ intelxl->queue = le16_to_cpu ( buf->vsi.queue[0] );
+ intelxl->qset = le16_to_cpu ( buf->vsi.qset[0] );
DBGC ( intelxl, "INTELXL %p VSI %#04x queue %#04x qset %#04x\n",
intelxl, intelxl->vsi, intelxl->queue, intelxl->qset );
@@ -483,24 +548,25 @@ static int intelxl_admin_vsi ( struct intelxl_nic *intelxl ) {
* @ret rc Return status code
*/
static int intelxl_admin_promisc ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_promisc_params *promisc = &cmd.params.promisc;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_promisc_params *promisc;
uint16_t flags;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_PROMISC );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_PROMISC );
flags = ( INTELXL_ADMIN_PROMISC_FL_UNICAST |
INTELXL_ADMIN_PROMISC_FL_MULTICAST |
INTELXL_ADMIN_PROMISC_FL_BROADCAST |
INTELXL_ADMIN_PROMISC_FL_VLAN );
+ promisc = &cmd->params.promisc;
promisc->flags = cpu_to_le16 ( flags );
promisc->valid = cpu_to_le16 ( flags );
promisc->vsi = cpu_to_le16 ( intelxl->vsi );
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
return 0;
@@ -513,18 +579,19 @@ static int intelxl_admin_promisc ( struct intelxl_nic *intelxl ) {
* @ret rc Return status code
*/
static int intelxl_admin_autoneg ( struct intelxl_nic *intelxl ) {
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_autoneg_params *autoneg = &cmd.params.autoneg;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_autoneg_params *autoneg;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_AUTONEG );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_AUTONEG );
+ autoneg = &cmd->params.autoneg;
autoneg->flags = ( INTELXL_ADMIN_AUTONEG_FL_RESTART |
INTELXL_ADMIN_AUTONEG_FL_ENABLE );
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
return 0;
@@ -538,17 +605,18 @@ static int intelxl_admin_autoneg ( struct intelxl_nic *intelxl ) {
*/
static int intelxl_admin_link ( struct net_device *netdev ) {
struct intelxl_nic *intelxl = netdev->priv;
- struct intelxl_admin_descriptor cmd;
- struct intelxl_admin_link_params *link = &cmd.params.link;
+ struct intelxl_admin_descriptor *cmd;
+ struct intelxl_admin_link_params *link;
int rc;
/* Populate descriptor */
- memset ( &cmd, 0, sizeof ( cmd ) );
- cmd.opcode = cpu_to_le16 ( INTELXL_ADMIN_LINK );
+ cmd = intelxl_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXL_ADMIN_LINK );
+ link = &cmd->params.link;
link->notify = INTELXL_ADMIN_LINK_NOTIFY;
/* Issue command */
- if ( ( rc = intelxl_admin_command ( intelxl, &cmd ) ) != 0 )
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
return rc;
DBGC ( intelxl, "INTELXL %p PHY %#02x speed %#02x status %#02x\n",
intelxl, link->phy, link->speed, link->status );
@@ -577,6 +645,7 @@ static void intelxl_refill_admin ( struct intelxl_nic *intelxl ) {
/* Update tail pointer */
tail = ( ( admin->index + INTELXL_ADMIN_NUM_DESC - 1 ) %
INTELXL_ADMIN_NUM_DESC );
+ wmb();
writel ( tail, admin_regs + regs->tail );
}
@@ -588,39 +657,42 @@ static void intelxl_refill_admin ( struct intelxl_nic *intelxl ) {
static void intelxl_poll_admin ( struct net_device *netdev ) {
struct intelxl_nic *intelxl = netdev->priv;
struct intelxl_admin *admin = &intelxl->event;
- struct intelxl_admin_descriptor *desc;
+ struct intelxl_admin_descriptor *evt;
+ union intelxl_admin_buffer *buf;
/* Check for events */
while ( 1 ) {
- /* Get next event descriptor */
- desc = &admin->desc[admin->index % INTELXL_ADMIN_NUM_DESC];
+ /* Get next event descriptor and data buffer */
+ evt = &admin->desc[ admin->index % INTELXL_ADMIN_NUM_DESC ];
+ buf = &admin->buf[ admin->index % INTELXL_ADMIN_NUM_DESC ];
/* Stop if descriptor is not yet completed */
- if ( ! ( desc->flags & INTELXL_ADMIN_FL_DD ) )
+ if ( ! ( evt->flags & INTELXL_ADMIN_FL_DD ) )
return;
DBGC2 ( intelxl, "INTELXL %p admin event %#x:\n",
intelxl, admin->index );
- DBGC2_HDA ( intelxl, virt_to_phys ( desc ), desc,
- sizeof ( *desc ) );
+ DBGC2_HDA ( intelxl, virt_to_phys ( evt ), evt,
+ sizeof ( *evt ) );
+ if ( evt->flags & cpu_to_le16 ( INTELXL_ADMIN_FL_BUF ) ) {
+ DBGC2_HDA ( intelxl, virt_to_phys ( buf ), buf,
+ le16_to_cpu ( evt->len ) );
+ }
/* Handle event */
- switch ( desc->opcode ) {
+ switch ( evt->opcode ) {
case cpu_to_le16 ( INTELXL_ADMIN_LINK ):
intelxl_admin_link ( netdev );
break;
default:
DBGC ( intelxl, "INTELXL %p admin event %#x "
"unrecognised opcode %#04x\n", intelxl,
- admin->index, le16_to_cpu ( desc->opcode ) );
+ admin->index, le16_to_cpu ( evt->opcode ) );
break;
}
- /* Clear event completion flag */
- desc->flags = 0;
- wmb();
-
- /* Update index and refill queue */
+ /* Reset descriptor and refill queue */
+ intelxl_admin_event_init ( intelxl, admin->index );
admin->index++;
intelxl_refill_admin ( intelxl );
}
@@ -633,6 +705,7 @@ static void intelxl_poll_admin ( struct net_device *netdev ) {
* @ret rc Return status code
*/
static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
+ unsigned int i;
int rc;
/* Create admin event queue */
@@ -643,6 +716,10 @@ static int intelxl_open_admin ( struct intelxl_nic *intelxl ) {
if ( ( rc = intelxl_create_admin ( intelxl, &intelxl->command ) ) != 0 )
goto err_create_command;
+ /* Initialise all admin event queue descriptors */
+ for ( i = 0 ; i < INTELXL_ADMIN_NUM_DESC ; i++ )
+ intelxl_admin_event_init ( intelxl, i );
+
/* Post all descriptors to event queue */
intelxl_refill_admin ( intelxl );
diff --git a/src/drivers/net/intelxl.h b/src/drivers/net/intelxl.h
index 138fc2ef..0175c1f9 100644
--- a/src/drivers/net/intelxl.h
+++ b/src/drivers/net/intelxl.h
@@ -319,6 +319,8 @@ union intelxl_admin_buffer {
struct intelxl_admin_switch_buffer sw;
/** Get VSI Parameters data buffer */
struct intelxl_admin_vsi_buffer vsi;
+ /** Alignment padding */
+ uint8_t pad[INTELXL_ALIGN];
} __attribute__ (( packed ));
/** Admin queue descriptor */
@@ -358,6 +360,8 @@ struct intelxl_admin_descriptor {
struct intelxl_admin {
/** Descriptors */
struct intelxl_admin_descriptor *desc;
+ /** Data buffers */
+ union intelxl_admin_buffer *buf;
/** Queue index */
unsigned int index;
@@ -365,8 +369,6 @@ struct intelxl_admin {
unsigned int base;
/** Register offsets */
const struct intelxl_admin_offsets *regs;
- /** Data buffer */
- union intelxl_admin_buffer *buffer;
};
/**