diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-08-16 15:53:41 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-08-16 19:31:06 +0100 |
commit | c5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e (patch) | |
tree | 0b454143bb57b64502f9bdfbedc2ef1944aa4633 | |
parent | 04879352c4f5fbb4f1aeaf9b644c2b8408847894 (diff) | |
download | ipxe-c5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e.tar.gz |
[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.c | 45 | ||||
-rw-r--r-- | src/drivers/net/intelxlvf.h | 14 |
2 files changed, 58 insertions, 1 deletions
diff --git a/src/drivers/net/intelxlvf.c b/src/drivers/net/intelxlvf.c index e30d8c6db..083195513 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 783c85643..95ddf9474 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 */ |