From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f228.google.com (mail-pl1-f228.google.com [209.85.214.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE2D94A204E for ; Tue, 1 Sep 2026 19:18:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.228 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788290321; cv=none; b=U74nj0KvZK8oeSsDLz4EiSXfyhhJVtCiPCruQVBE8lIbjcVYf5IC1RmQM/6cDzK4pXdu59bjpl35tLsxmMrGl6biUmNpFJXz6iwvAv/+f2CBiS/0b4POCzLLEBZskgMTBZDtm/YzIYx2x+vsdurQllSNDXYw/0Xj+xEvi/az9r0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788290321; c=relaxed/simple; bh=iueqeIbJYnCT9WVs/BpHtEDifuD6Tb8T9a83N/PgUVA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Cf9MFlPVKHaCTTKIWP+C4EC8Oz5eiSDapH0twHVvzLe9sU/VeqxE3tg5B4N3I9nhxkDwmxSApVzPhqqm5xeU10sXqhkCNo1KqCupYrjE7Xw4EfClxV2G5+Cb7uXDZc46MU+xPvh3S3yYFM0T/hkQlf2adUU44E6DGBI33MgIGFA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=JJsh8oed; arc=none smtp.client-ip=209.85.214.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="JJsh8oed" Received: by mail-pl1-f228.google.com with SMTP id d9443c01a7336-2cace91f112so1700475ad.0 for ; Tue, 01 Sep 2026 12:18:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788290319; x=1788895119; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=W1gNnpuofqG8j7WBbKQviqP7swsJK+cjy5dt+o+RP90=; b=sW2/ymo8rCv9gYSaFsoLnc/VCwlj9yjsZE66ahTYT4sMGWX2nS+2FfR6bNQlmP9P0d Sdxocz+vxy7sxIk/Tg7G/7OvIKiXtRMahakathhCDvZUhwo6yID7UR6K8404JRwnHD/W r9FC9bapSOp64B8G/RV6PJmYOiKsLFt5GCsS+qtmOnxKQHhFgU/DSVEiCzXFrDyKEm0L KY4XF6J++mt5Zf82efA//RxT8tsxMj889je4AKBi7IDHpYUvG5IvVrshWnEnGy+qs+XE YksruLkM9Ni+RgmQbpE67zNlDboU06S0oxv4aQgyq6rB3PbOyGHKM+oOnE8CouAN1dNJ Xofg== X-Forwarded-Encrypted: i=1; AKwUvByhib51Pn5naCf5+OEabAoUOZvDiG5Jf29ImS1H010yAUQVrh8d/HyO6tQcB1BRo/MYGV9N2e+Pt51n7Ws=@vger.kernel.org X-Gm-Message-State: AFuF++kH3Lci682aDFFGCpRDde919fBtsj612Zk1CSbRfjI8pZQ+boQz qEXp0IezENB491y+Jhyt1uLVJywVx8VaI7hmxTlolNqhrLMFu5rJNc87KWbFWWaCeZjVAB8hIkC XfuNIPUrK9EQyqaJiJtYtl+bDnVXA8lDfH3ueaEdVwLcLVFesivuxjrOGrwnU/L8jreBPg4bXJd Z/gAJ0u7qKNJ5EvbusCifa/WDzEDCB/3IodIWLI3Ylo+HUgsJR2LZ9mM2H8JmMQ6TRUItpyvelE dQ7fRPIP2YHHsuppokel/88yw== X-Gm-Gg: AYBFou2P7lbzXLZFrNs5RUWs77zhhT81VtrQSOIwpk7pK5IhpcqYS0qCxyNE0VIBSFx VSJvp6uNAZNg51ZDzkLleLU2RJLR0UF7IqUFDBqXldQBlWYTtgSq+kXx4R2hpBrH7D8DOCq0oYm I/nFIOdfjI5vtwEGvZOhujNFEIyr++ZH1o+6RauL95S0dpu1oAzknjxHs6AQEzHfGSdwSj4Q+v3 aE5CTSXedAyRCqy9L+OKTJC0mD85xRFxmBjR1+Vlqr9m/GwkH3zMbzeRLiUx3dq/PySTKCAjhDI ysqAtfOKvoM895XxyxIAuvc9hafR2A0VAGQkcdhnRht9BhD2PQSHtyPg1K0bWh4qK39+OPiqZq3 1OA9W8JWz3JmwF78/iFmk8onxMNR3y1+lGqC/Hwz1cDVXY0MVpACtdNMzM+pLAjUQ1Us2uNfMQM 6mtjZHemHmDwB3p0BWSnpttA7jU3HKKr3qSzwFSIvNXA== X-Received: by 2002:a17:90b:2801:b0:38f:18f9:785 with SMTP id 98e67ed59e1d1-39ae829c9demr490878a91.8.1788290319178; Tue, 01 Sep 2026 12:18:39 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-23.dlp.protect.broadcom.com. [144.49.247.23]) by smtp-relay.gmail.com with ESMTPS id 98e67ed59e1d1-3990d4bb9c4sm1317050a91.7.2026.09.01.12.18.38 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 01 Sep 2026 12:18:39 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-2d6fb956002so2294335ad.1 for ; Tue, 01 Sep 2026 12:18:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1788290317; x=1788895117; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=W1gNnpuofqG8j7WBbKQviqP7swsJK+cjy5dt+o+RP90=; b=JJsh8oed9OsHtqN2khwlQMUC3jQsVvACM0uIGGwjUPnrI2sGSiAn/eVrAOZpKD8kci /FB1dMVWyS2lQsrLHz1J2r41s187GcMBXbn4sIMkti3GYJ1SqKWBJXlN6Jm95XE7q1x8 sAshdb2L5gp/XK2ODetzbdSk7SaeDfB5xw9/U= X-Forwarded-Encrypted: i=1; AKwUvBzCnqMl+DqX90bqLdAi68Tevzohd1UkoRnZzviF7CO+1aqEiN2gw6aOAziS/pgtQMcBE+wuvMR0Du6L8bM=@vger.kernel.org X-Received: by 2002:a17:903:234b:b0:2d8:d4d3:3fc0 with SMTP id d9443c01a7336-2dae5f03d3emr5623195ad.20.1788290317362; Tue, 01 Sep 2026 12:18:37 -0700 (PDT) X-Received: by 2002:a17:903:234b:b0:2d8:d4d3:3fc0 with SMTP id d9443c01a7336-2dae5f03d3emr5622285ad.20.1788290316606; Tue, 01 Sep 2026 12:18:36 -0700 (PDT) Received: from localhost.localdomain ([192.19.203.250]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-32f07b79cf9sm186440eec.18.2026.09.01.12.18.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Sep 2026 12:18:35 -0700 (PDT) From: Bhargava Marreddy To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michael.chan@broadcom.com, pavan.chebbi@broadcom.com, vsrama-krishna.nemani@broadcom.com, vikas.gupta@broadcom.com, Bhargava Marreddy , Dharmender Garg Subject: [PATCH net-next 6/7] bnge: Create NQ0 during probe and keep active across open/close Date: Wed, 2 Sep 2026 00:47:27 +0530 Message-ID: <20260901191728.643212-7-bhargava.marreddy@broadcom.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260901191728.643212-1-bhargava.marreddy@broadcom.com> References: <20260901191728.643212-1-bhargava.marreddy@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Set up NQ0 via bnge_setup_nq0() during probe and free it via bnge_free_nq0() at remove. Skip NQ0 in open/close ring, IRQ, and NAPI helpers once BNGE_NAPI_FLAG_NQ0 is set. Also guard bnge_napi_poll() against stale completions for rings freed by bnge_free_nq_tree(). The previous patch already added the bnge_quiesce_nq0()/bnge_resume_nq0() guard around bnge_free_core()'s teardown and bnge_alloc_core()'s rebuild, so NQ0 is safe to leave active across close/open from the moment BNGE_NAPI_FLAG_NQ0 is set below. Signed-off-by: Bhargava Marreddy Reviewed-by: Dharmender Garg Reviewed-by: Vikas Gupta --- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 237 +++++++++++++++++- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 1 + .../net/ethernet/broadcom/bnge/bnge_rmem.c | 3 +- .../net/ethernet/broadcom/bnge/bnge_txrx.c | 15 ++ 4 files changed, 244 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c index 10d54568f2c5..d11c404acd4e 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c @@ -527,6 +527,9 @@ static void bnge_free_nq_arrays(struct bnge_net *bn) for (i = 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi = bn->bnapi[i]; + if (BNGE_NQ0_NAPI(bnapi)) + continue; + bnge_free_nq_desc_arr(&bnapi->nq_ring); } } @@ -539,6 +542,9 @@ static int bnge_alloc_nq_arrays(struct bnge_net *bn) for (i = 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi = bn->bnapi[i]; + if (BNGE_NQ0_NAPI(bnapi)) + continue; + rc = bnge_alloc_nq_desc_arr(&bnapi->nq_ring, bn->cp_nr_pages); if (rc) goto err_free_nq_arrays; @@ -564,7 +570,8 @@ static void bnge_free_nq_tree(struct bnge_net *bn) nqr = &bnapi->nq_ring; ring = &nqr->ring_struct; - bnge_free_ring(bd, &ring->ring_mem); + if (!BNGE_NQ0_NAPI(bnapi)) + bnge_free_ring(bd, &ring->ring_mem); if (!nqr->cp_ring_arr) continue; @@ -592,6 +599,9 @@ static void bnge_quiesce_nq0(struct bnge_net *bn) if (!BNGE_NQ0_NAPI(bnapi)) return; + if (test_and_set_bit(BNGE_NAPI_FLAG_NQ0_QUIESCED, &bnapi->flags)) + return; + ring = &nqr->ring_struct; bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons); synchronize_irq(bd->irq_tbl[ring->map_idx].vector); @@ -606,6 +616,9 @@ static void bnge_resume_nq0(struct bnge_net *bn) if (!BNGE_NQ0_NAPI(bnapi)) return; + if (!test_and_clear_bit(BNGE_NAPI_FLAG_NQ0_QUIESCED, &bnapi->flags)) + return; + napi_enable_locked(&bnapi->napi); bnge_db_nq_arm(bn, &nqr->nq_db, nqr->nq_raw_cons); } @@ -658,11 +671,13 @@ static int bnge_alloc_nq_tree(struct bnge_net *bn) nqr->bnapi = bnapi; ring = &nqr->ring_struct; - rc = bnge_alloc_ring(bd, &ring->ring_mem); - if (rc) - goto err_free_nq_tree; + if (!BNGE_NQ0_NAPI(bnapi)) { + rc = bnge_alloc_ring(bd, &ring->ring_mem); + if (rc) + goto err_free_nq_tree; - ring->map_idx = ulp_msix + i; + ring->map_idx = ulp_msix + i; + } if (i < bd->rx_nr_rings) { cp_count++; @@ -1236,10 +1251,14 @@ static int bnge_init_ring_grps(struct bnge_net *bn, bool irq_re_init) bn->grp_info[i].fw_grp_id = INVALID_HW_RING_ID; bn->grp_info[i].rx_fw_ring_id = INVALID_HW_RING_ID; bn->grp_info[i].agg_fw_ring_id = INVALID_HW_RING_ID; - bn->grp_info[i].nq_fw_ring_id = INVALID_HW_RING_ID; if (irq_re_init) bn->grp_info[i].fw_stats_ctx = INVALID_HW_RING_ID; + + if (BNGE_NQ0_NAPI(bn->bnapi[i])) + continue; + + bn->grp_info[i].nq_fw_ring_id = INVALID_HW_RING_ID; } return 0; @@ -1442,8 +1461,11 @@ static void bnge_init_nq_tree(struct bnge_net *bn) struct bnge_nq_ring_info *nqr = &bn->bnapi[i]->nq_ring; struct bnge_ring_struct *ring = &nqr->ring_struct; - nqr->nq_raw_cons = 0; - ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + if (!BNGE_NQ0_NAPI(bn->bnapi[i])) { + nqr->nq_raw_cons = 0; + ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + } + for (j = 0; j < nqr->cp_ring_count; j++) { struct bnge_cp_ring_info *cpr = &nqr->cp_ring_arr[j]; @@ -1970,6 +1992,9 @@ static int bnge_hwrm_nq_ring_alloc(struct bnge_net *bn, int index) unsigned int vector; int rc; + if (BNGE_NQ0_NAPI(bnapi)) + return 0; + vector = bd->irq_tbl[map_idx].vector; disable_irq_nosync(vector); rc = hwrm_ring_alloc_send_msg(bn, ring, type, map_idx); @@ -2402,6 +2427,9 @@ static void bnge_disable_int(struct bnge_net *bn) struct bnge_nq_ring_info *nqr; struct bnge_ring_struct *ring; + if (BNGE_NQ0_NAPI(bnapi)) + continue; + nqr = &bnapi->nq_ring; ring = &nqr->ring_struct; @@ -2417,9 +2445,10 @@ static void bnge_disable_int_sync(struct bnge_net *bn) bnge_disable_int(bn); for (i = 0; i < bd->nq_nr_rings; i++) { - int map_idx = bnge_cp_num_to_irq_num(bn, i); + if (BNGE_NQ0_NAPI(bn->bnapi[i])) + continue; - synchronize_irq(bd->irq_tbl[map_idx].vector); + synchronize_irq(bd->irq_tbl[bnge_cp_num_to_irq_num(bn, i)].vector); } } @@ -2432,6 +2461,9 @@ static void bnge_enable_int(struct bnge_net *bn) struct bnge_napi *bnapi = bn->bnapi[i]; struct bnge_nq_ring_info *nqr; + if (BNGE_NQ0_NAPI(bnapi)) + continue; + nqr = &bnapi->nq_ring; bnge_db_nq_arm(bn, &nqr->nq_db, nqr->nq_raw_cons); } @@ -2448,6 +2480,8 @@ static void bnge_disable_napi(struct bnge_net *bn) for (i = 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi = bn->bnapi[i]; + if (BNGE_NQ0_NAPI(bnapi)) + continue; napi_disable_locked(&bnapi->napi); } } @@ -2464,6 +2498,8 @@ static void bnge_enable_napi(struct bnge_net *bn) bnapi->in_reset = false; bnapi->tx_fault = 0; + if (BNGE_NQ0_NAPI(bnapi)) + continue; napi_enable_locked(&bnapi->napi); } } @@ -2612,6 +2648,9 @@ static void bnge_hwrm_ring_free(struct bnge_net *bn, bool close_path) for (j = 0; j < nqr->cp_ring_count && nqr->cp_ring_arr; j++) bnge_hwrm_cp_ring_free(bn, &nqr->cp_ring_arr[j]); + if (BNGE_NQ0_NAPI(bnapi)) + continue; + ring = &nqr->ring_struct; if (ring->fw_ring_id != INVALID_HW_RING_ID_32BIT) { hwrm_ring_free_send_msg(bn, ring, @@ -2673,6 +2712,9 @@ static void bnge_free_irq(struct bnge_net *bn) for (i = 0; i < bd->nq_nr_rings; i++) { int map_idx = bnge_cp_num_to_irq_num(bn, i); + if (BNGE_NQ0_NAPI(bn->bnapi[i])) + continue; + irq = &bd->irq_tbl[map_idx]; if (irq->requested) { if (irq->have_cpumask) { @@ -2701,6 +2743,9 @@ static int bnge_request_irq(struct bnge_net *bn) int map_idx = bnge_cp_num_to_irq_num(bn, i); struct bnge_irq *irq = &bd->irq_tbl[map_idx]; + if (BNGE_NQ0_NAPI(bn->bnapi[i])) + continue; + rc = request_irq(irq->vector, irq->handler, 0, irq->name, bn->bnapi[i]); if (rc) @@ -2840,6 +2885,10 @@ static void bnge_init_napi(struct bnge_net *bn) for (i = 0; i < bd->nq_nr_rings; i++) { bnapi = bn->bnapi[i]; + + if (BNGE_NQ0_NAPI(bnapi)) + continue; + netif_napi_add_config_locked(bn->netdev, &bnapi->napi, bnge_napi_poll, bnapi->index); } @@ -2858,6 +2907,9 @@ static void bnge_del_napi(struct bnge_net *bn) for (i = 0; i < bd->nq_nr_rings; i++) { struct bnge_napi *bnapi = bn->bnapi[i]; + if (BNGE_NQ0_NAPI(bnapi)) + continue; + __netif_napi_del_locked(&bnapi->napi); } @@ -3237,6 +3289,8 @@ static void bnge_close_core(struct bnge_net *bn) clear_bit(BNGE_STATE_STATS_ENABLE, &bn->state); spin_unlock_bh(&bn->stats_lock); + bnge_quiesce_nq0(bn); + bnge_free_all_rings_bufs(bn); bnge_free_irq(bn); bnge_del_napi(bn); @@ -3467,6 +3521,159 @@ static void bnge_init_ring_params(struct bnge_net *bn) bn->netdev->cfg->hds_thresh = max(BNGE_DEFAULT_RX_COPYBREAK, rx_size); } +static void bnge_free_nq0(struct bnge_net *bn) +{ + struct bnge_nq_ring_info *nqr; + struct bnge_ring_struct *ring; + struct bnge_dev *bd = bn->bd; + struct bnge_napi *bnapi; + struct bnge_irq *irq; + + bnapi = bn->bnapi[BNGE_NQ0_NAPI_IDX]; + nqr = &bnapi->nq_ring; + ring = &nqr->ring_struct; + irq = &bd->irq_tbl[ring->map_idx]; + + if (!BNGE_NQ0_NAPI(bnapi)) { + /* A previous bnge_setup_nq0() could have failed + * leaving behind an active irq. + */ + goto free_irq; + } + + clear_bit(BNGE_NAPI_FLAG_NQ0, &bnapi->flags); + clear_bit(BNGE_NAPI_FLAG_NQ0_QUIESCED, &bnapi->flags); + + /* Unlike the other NQs, NQ0's NAPI is left enabled by bnge_disable_napi() + * so it can keep processing async events while the interface is + * administratively down. It is explicitly disabled below, or was never + * enabled if netdev was never opened (netif_napi_add default). + */ + bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons); + synchronize_irq(irq->vector); + + hwrm_ring_free_send_msg(bn, ring, + RING_FREE_REQ_RING_TYPE_NQ, + INVALID_HW_RING_ID); + ring->fw_ring_id = INVALID_HW_RING_ID; + bn->grp_info[0].nq_fw_ring_id = INVALID_HW_RING_ID; + +free_irq: + if (irq->requested) { + if (irq->have_cpumask) { + irq_set_affinity_hint(irq->vector, NULL); + free_cpumask_var(irq->cpu_mask); + irq->have_cpumask = 0; + } + free_irq(irq->vector, bnapi); + irq->requested = 0; + + netdev_lock(bn->netdev); + napi_disable_locked(&bnapi->napi); + __netif_napi_del_locked(&bnapi->napi); + netdev_unlock(bn->netdev); + + /* We called __netif_napi_del_locked(), we need + * grace period before freeing napi structures. + */ + synchronize_net(); + } + + bnge_free_ring(bd, &ring->ring_mem); + bnge_free_nq_desc_arr(nqr); +} + +static int bnge_setup_nq0(struct bnge_net *bn) +{ + struct bnge_nq_ring_info *nqr; + struct bnge_ring_struct *ring; + struct bnge_dev *bd = bn->bd; + struct bnge_napi *bnapi; + struct bnge_irq *irq; + int map_idx, rc; + + bnapi = bn->bnapi[BNGE_NQ0_NAPI_IDX]; + if (BNGE_NQ0_NAPI(bnapi)) + return 0; + + nqr = &bnapi->nq_ring; + ring = &nqr->ring_struct; + rc = bnge_alloc_nq_desc_arr(&bnapi->nq_ring, bn->cp_nr_pages); + if (rc) + return -ENOMEM; + + bnge_init_nq_ring_struct(bn, nqr); + rc = bnge_alloc_ring(bd, &ring->ring_mem); + if (rc) + goto err_free_nq_desc_arr; + + map_idx = bnge_aux_get_msix(bd); + ring->map_idx = map_idx; + irq = &bd->irq_tbl[map_idx]; + irq->handler = bnge_msix; + + netdev_lock(bn->netdev); + netif_napi_add_config_locked(bn->netdev, &bnapi->napi, + bnge_napi_poll, bnapi->index); + netdev_unlock(bn->netdev); + + snprintf(irq->name, sizeof(bd->irq_tbl[0].name), "%s-%s-%d", "bnge", + "nq", map_idx); + rc = request_irq(irq->vector, irq->handler, 0, irq->name, bnapi); + if (rc) + goto err_del_napi; + + netdev_lock(bn->netdev); + netif_napi_set_irq_locked(&bnapi->napi, irq->vector); + netdev_unlock(bn->netdev); + irq->requested = 1; + + if (zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL)) { + int numa_node = dev_to_node(&bd->pdev->dev); + + irq->have_cpumask = 1; + cpumask_set_cpu(cpumask_local_spread(BNGE_NQ0_NAPI_IDX, numa_node), + irq->cpu_mask); + rc = irq_set_affinity_hint(irq->vector, irq->cpu_mask); + if (rc) { + netdev_warn(bn->netdev, + "Set affinity failed, IRQ = %d\n", + irq->vector); + goto err_free_irq; + } + } + + rc = bnge_hwrm_nq_ring_alloc(bn, BNGE_NQ0_NAPI_IDX); + if (rc) + goto err_free_irq; + + netdev_lock(bn->netdev); + napi_enable_locked(&bnapi->napi); + netdev_unlock(bn->netdev); + bnge_db_nq_arm(bn, &nqr->nq_db, nqr->nq_raw_cons); + + set_bit(BNGE_NAPI_FLAG_NQ0, &bnapi->flags); + + return 0; + +err_free_irq: + if (irq->have_cpumask) { + irq_set_affinity_hint(irq->vector, NULL); + free_cpumask_var(irq->cpu_mask); + irq->have_cpumask = 0; + } + free_irq(irq->vector, bnapi); + irq->requested = 0; +err_del_napi: + netdev_lock(bn->netdev); + __netif_napi_del_locked(&bnapi->napi); + netdev_unlock(bn->netdev); + bnge_free_ring(bd, &ring->ring_mem); +err_free_nq_desc_arr: + bnge_free_nq_desc_arr(nqr); + return rc; +} + int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs) { struct net_device *netdev; @@ -3594,14 +3801,20 @@ int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs) if (rc) goto err_free_bnapi_mem; + rc = bnge_setup_nq0(bn); + if (rc) + goto err_free_ring_grps; + rc = register_netdev(netdev); if (rc) { dev_err(bd->dev, "Register netdev failed rc: %d\n", rc); - goto err_free_ring_grps; + goto err_free_nq0; } return 0; +err_free_nq0: + bnge_free_nq0(bn); err_free_ring_grps: bnge_free_ring_grps(bn); err_free_bnapi_mem: @@ -3624,6 +3837,8 @@ void bnge_netdev_free(struct bnge_dev *bd) unregister_netdev(netdev); + bnge_free_nq0(bn); + timer_shutdown_sync(&bn->timer); cancel_work_sync(&bn->sp_task); bn->sp_event = 0; diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h index 4d84f109ad5f..e2fb15fd62b6 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h @@ -543,6 +543,7 @@ struct bnge_tx_ring_info { enum bnge_napi_flag { BNGE_NAPI_FLAG_NQ0, + BNGE_NAPI_FLAG_NQ0_QUIESCED, }; #define BNGE_NQ0_NAPI(bnapi) (test_bit(BNGE_NAPI_FLAG_NQ0, &(bnapi)->flags)) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c index e0ddb2800c54..22fd4eeb3213 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c @@ -450,7 +450,8 @@ void bnge_init_ring_struct(struct bnge_net *bn) struct bnge_tx_ring_info *txr; struct bnge_ring_struct *ring; - bnge_init_nq_ring_struct(bn, &bnapi->nq_ring); + if (!BNGE_NQ0_NAPI(bnapi)) + bnge_init_nq_ring_struct(bn, &bnapi->nq_ring); rxr = bnapi->rx_ring; if (!rxr) diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c index 7d45e057f2e8..dcec6fdced30 100644 --- a/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c +++ b/drivers/net/ethernet/broadcom/bnge/bnge_txrx.c @@ -1375,6 +1375,21 @@ int bnge_napi_poll(struct napi_struct *napi, int budget) break; idx = BNGE_NQ_HDL_IDX(idx); + + /* NQ0 keeps running while administratively down to + * process async events, but its cp_ring_arr is torn + * down (and cp_ring_count zeroed) by + * bnge_free_nq_tree() while down. Guard against a + * stray/late CQ notification arriving in that state + * instead of dereferencing a freed or out-of-range + * cp_ring_arr. + */ + if (unlikely(!nqr->cp_ring_arr || + idx >= nqr->cp_ring_count)) { + raw_cons = NEXT_RAW_CMP(raw_cons); + continue; + } + cpr = &nqr->cp_ring_arr[idx]; cpr->had_nqe_notify = 1; cpr->toggle = NQE_CN_TOGGLE(type); -- 2.47.3