git: bb98012e39ac - stable/12 - ena: Prevent LLQ initialization when membar isn't exposed

From: Marcin Wojtas <mw_at_FreeBSD.org>
Date: Tue, 26 Jul 2022 19:33:22 UTC
The branch stable/12 has been updated by mw:

URL: https://cgit.FreeBSD.org/src/commit/?id=bb98012e39ac55ed2d9a93b90404dfc3d2e77f7f

commit bb98012e39ac55ed2d9a93b90404dfc3d2e77f7f
Author:     Dawid Gorecki <dgr@semihalf.com>
AuthorDate: 2022-06-10 09:18:08 +0000
Commit:     Marcin Wojtas <mw@FreeBSD.org>
CommitDate: 2022-07-26 19:33:03 +0000

    ena: Prevent LLQ initialization when membar isn't exposed
    
    The ena_com_config_dev_mode() function performs many LLQ related
    calculations and sends an admin command to configure LLQ in the device.
    
    All the LLQ related operations are unnecessary if the driver fails to
    find LLQ memory bar.
    
    Move LLQ memory bar allocation to separate helper function
    ena_map_llq_mem_bar and execute this function before LLQ configuration.
    If the LLQ memory bar cannot be allocated, then LLQ configuration is
    skipped.
    
    Obtained from: Semihalf
    MFC after: 2 weeks
    Sponsored by: Amazon, Inc.
    
    (cherry picked from commit 90232d18ca4f7a5a3073a8279a9b9d3228df5f87)
---
 sys/dev/ena/ena.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/sys/dev/ena/ena.c b/sys/dev/ena/ena.c
index e21f7bbcc2b0..64066896907e 100644
--- a/sys/dev/ena/ena.c
+++ b/sys/dev/ena/ena.c
@@ -155,6 +155,7 @@ static int	ena_setup_ifnet(device_t, struct ena_adapter *,
 static int	ena_enable_wc(device_t, struct resource *);
 static int	ena_set_queues_placement_policy(device_t, struct ena_com_dev *,
     struct ena_admin_feature_llq_desc *, struct ena_llq_configurations *);
+static int	ena_map_llq_mem_bar(device_t, struct ena_com_dev *);
 static uint32_t	ena_calc_max_io_queue_num(device_t, struct ena_com_dev *,
     struct ena_com_dev_get_features_ctx *);
 static int	ena_calc_io_queue_size(struct ena_calc_queue_size_ctx *);
@@ -2575,8 +2576,7 @@ ena_set_queues_placement_policy(device_t pdev, struct ena_com_dev *ena_dev,
     struct ena_admin_feature_llq_desc *llq,
     struct ena_llq_configurations *llq_default_configurations)
 {
-	struct ena_adapter *adapter = device_get_softc(pdev);
-	int rc, rid;
+	int rc;
 	uint32_t llq_feature_mask;
 
 	llq_feature_mask = 1 << ENA_ADMIN_LLQ;
@@ -2587,17 +2587,28 @@ ena_set_queues_placement_policy(device_t pdev, struct ena_com_dev *ena_dev,
 		return (0);
 	}
 
+	if (ena_dev->mem_bar == NULL) {
+		ena_log(pdev, WARN,
+		    "LLQ is advertised as supported but device doesn't expose mem bar.\n");
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		return (0);
+	}
+
 	rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations);
 	if (unlikely(rc != 0)) {
 		ena_log(pdev, WARN, "Failed to configure the device mode. "
 		    "Fallback to host mode policy.\n");
 		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
-		return (0);
 	}
 
-	/* Nothing to config, exit */
-	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
-		return (0);
+	return (0);
+}
+
+static int
+ena_map_llq_mem_bar(device_t pdev, struct ena_com_dev *ena_dev)
+{
+	struct ena_adapter *adapter = device_get_softc(pdev);
+	int rc, rid;
 
 	/* Try to allocate resources for LLQ bar */
 	rid = PCIR_BAR(ENA_MEM_BAR);
@@ -3599,6 +3610,12 @@ ena_attach(device_t pdev)
 
 	set_default_llq_configurations(&llq_config, &get_feat_ctx.llq);
 
+	rc = ena_map_llq_mem_bar(pdev, ena_dev);
+	if (unlikely(rc != 0)) {
+		ena_log(pdev, ERR, "failed to map ENA mem bar");
+		goto err_com_free;
+	}
+
 	rc = ena_set_queues_placement_policy(pdev, ena_dev, &get_feat_ctx.llq,
 	     &llq_config);
 	if (unlikely(rc != 0)) {