]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[intelxl] Explicitly request a single queue pair for virtual functions
authorMichael Brown <mcb30@ipxe.org>
Tue, 16 Aug 2022 14:53:41 +0000 (15:53 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 16 Aug 2022 18:31:06 +0000 (19:31 +0100)
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>
src/drivers/net/intelxlvf.c
src/drivers/net/intelxlvf.h

index e30d8c6db8ce46852c99c3899eb9d20caa3b9c60..083195513a50b96add0979fe4f8cd532a49e6290 100644 (file)
@@ -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:
index 783c85643e4068c08fe1c1328fa9766236074ca0..95ddf9474d8a7ca48645de234fc4c436a7efbb2f 100644 (file)
@@ -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 */