aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-08-16 15:53:41 +0100
committerMichael Brown <mcb30@ipxe.org>2022-08-16 19:31:06 +0100
commitc5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e (patch)
tree0b454143bb57b64502f9bdfbedc2ef1944aa4633
parent04879352c4f5fbb4f1aeaf9b644c2b8408847894 (diff)
downloadipxe-c5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e.zip
ipxe-c5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e.tar.gz
ipxe-c5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e.tar.bz2
[intelxl] Explicitly request a single queue pair for virtual functions
Current versions of the E810 PF driver fail to set the number of in-use queue pairs in response to the CONFIG_VSI_QUEUES message. When the number of in-use queue pairs is less than the number of available queue pairs, this results in some packets being directed to nonexistent receive queues and hence silently dropped. Work around this PF driver bug by explicitly configuring the number of available queue pairs via the REQUEST_QUEUES message. This message triggers a VF reset that, in turn, requires us to reopen the admin queue and issue an additional GET_RESOURCES message to restore the VF to a functional state. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/drivers/net/intelxlvf.c45
-rw-r--r--src/drivers/net/intelxlvf.h14
2 files changed, 58 insertions, 1 deletions
diff --git a/src/drivers/net/intelxlvf.c b/src/drivers/net/intelxlvf.c
index e30d8c6..0831955 100644
--- a/src/drivers/net/intelxlvf.c
+++ b/src/drivers/net/intelxlvf.c
@@ -395,7 +395,8 @@ static int intelxlvf_admin_get_resources ( struct net_device *netdev ) {
cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_RD | INTELXL_ADMIN_FL_BUF );
cmd->len = cpu_to_le16 ( sizeof ( buf->caps ) );
buf = intelxlvf_admin_command_buffer ( intelxl );
- buf->caps.caps = cpu_to_le32 ( INTELXLVF_ADMIN_CAP_L2 );
+ buf->caps.caps = cpu_to_le32 ( INTELXLVF_ADMIN_CAP_L2 |
+ INTELXLVF_ADMIN_CAP_RQPS );
/* Issue command */
if ( ( rc = intelxlvf_admin_command ( netdev ) ) != 0 )
@@ -462,6 +463,42 @@ static int intelxlvf_admin_stats ( struct net_device *netdev ) {
return 0;
}
+/**
+ * Configure number of queue pairs
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int intelxlvf_admin_request_qps ( struct net_device *netdev ) {
+ struct intelxl_nic *intelxl = netdev->priv;
+ struct intelxlvf_admin_descriptor *cmd;
+ union intelxlvf_admin_buffer *buf;
+ int rc;
+
+ /* Populate descriptor */
+ cmd = intelxlvf_admin_command_descriptor ( intelxl );
+ cmd->opcode = cpu_to_le16 ( INTELXLVF_ADMIN_SEND_TO_PF );
+ cmd->vopcode = cpu_to_le32 ( INTELXLVF_ADMIN_REQUEST_QPS );
+ cmd->flags = cpu_to_le16 ( INTELXL_ADMIN_FL_RD | INTELXL_ADMIN_FL_BUF );
+ cmd->len = cpu_to_le16 ( sizeof ( buf->rqps ) );
+ buf = intelxlvf_admin_command_buffer ( intelxl );
+ buf->rqps.count = cpu_to_le16 ( 1 );
+
+ /* Issue command (which will trigger a reset) */
+ if ( ( rc = intelxl_admin_command ( intelxl ) ) != 0 )
+ return rc;
+
+ /* Wait for reset to complete */
+ if ( ( rc = intelxlvf_reset_wait ( intelxl ) ) != 0 )
+ return rc;
+
+ /* Reestablish capabilities to reactivate VF after reset */
+ if ( ( rc = intelxlvf_admin_get_resources ( netdev ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
/******************************************************************************
*
* Network device interface
@@ -781,6 +818,11 @@ static int intelxlvf_probe ( struct pci_device *pci ) {
if ( ( rc = intelxlvf_admin_get_resources ( netdev ) ) != 0 )
goto err_get_resources;
+ /* Configure number of queue pairs, if applicable */
+ if ( ( intelxl->caps & INTELXLVF_ADMIN_CAP_RQPS ) &&
+ ( ( rc = intelxlvf_admin_request_qps ( netdev ) ) != 0 ) )
+ goto err_rqps;
+
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err_register_netdev;
@@ -789,6 +831,7 @@ static int intelxlvf_probe ( struct pci_device *pci ) {
unregister_netdev ( netdev );
err_register_netdev:
+ err_rqps:
err_get_resources:
err_version:
err_reset_admin:
diff --git a/src/drivers/net/intelxlvf.h b/src/drivers/net/intelxlvf.h
index 783c856..95ddf94 100644
--- a/src/drivers/net/intelxlvf.h
+++ b/src/drivers/net/intelxlvf.h
@@ -130,6 +130,9 @@ struct intelxlvf_admin_get_resources_buffer {
/** Layer 2 capabilities (add/remove MAC, configure promiscuous mode) */
#define INTELXLVF_ADMIN_CAP_L2 0x00000001
+/** Request Queues capabilities */
+#define INTELXLVF_ADMIN_CAP_RQPS 0x00000040
+
/** Admin Queue VF Status Change Event opcode */
#define INTELXLVF_ADMIN_STATUS 0x00000011
@@ -299,6 +302,15 @@ struct intelxlvf_admin_stats_buffer {
struct intelxlvf_admin_stats tx;
} __attribute__ (( packed ));
+/** Admin Queue VF Request Queues opcode */
+#define INTELXLVF_ADMIN_REQUEST_QPS 0x0000001d
+
+/** Admin Queue VF Request Queues data buffer */
+struct intelxlvf_admin_request_qps_buffer {
+ /** Number of queue pairs */
+ uint16_t count;
+} __attribute__ (( packed ));
+
/** Admin queue data buffer */
union intelxlvf_admin_buffer {
/** Original 40 Gigabit Ethernet data buffer */
@@ -321,6 +333,8 @@ union intelxlvf_admin_buffer {
struct intelxlvf_admin_irq_map_buffer irq;
/** VF Get Statistics data buffer */
struct intelxlvf_admin_stats_buffer stats;
+ /** VF Request Queues data buffer */
+ struct intelxlvf_admin_request_qps_buffer rqps;
} __attribute__ (( packed ));
/** Admin queue descriptor */