Thomas Bogendoerfer 776d31
From: Michael Chan <michael.chan@broadcom.com>
Thomas Bogendoerfer 776d31
Date: Fri, 3 Mar 2023 18:43:57 -0800
Thomas Bogendoerfer 776d31
Subject: bnxt_en: Avoid order-5 memory allocation for TPA data
Thomas Bogendoerfer 776d31
Patch-mainline: v6.3-rc2
Thomas Bogendoerfer 776d31
Git-commit: accd7e23693aaaa9aa0d3e9eca0ae77d1be80ab3
Thomas Bogendoerfer 776d31
References: bsc#1209079
Thomas Bogendoerfer 776d31
Thomas Bogendoerfer 776d31
The driver needs to keep track of all the possible concurrent TPA (GRO/LRO)
Thomas Bogendoerfer 776d31
completions on the aggregation ring.  On P5 chips, the maximum number
Thomas Bogendoerfer 776d31
of concurrent TPA is 256 and the amount of memory we allocate is order-5
Thomas Bogendoerfer 776d31
on systems using 4K pages.  Memory allocation failure has been reported:
Thomas Bogendoerfer 776d31
Thomas Bogendoerfer 776d31
NetworkManager: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0-1
Thomas Bogendoerfer 776d31
CPU: 15 PID: 2995 Comm: NetworkManager Kdump: loaded Not tainted 5.10.156 #1
Thomas Bogendoerfer 776d31
Hardware name: Dell Inc. PowerEdge R660/0M1CC5, BIOS 0.2.25 08/12/2022
Thomas Bogendoerfer 776d31
Call Trace:
Thomas Bogendoerfer 776d31
 dump_stack+0x57/0x6e
Thomas Bogendoerfer 776d31
 warn_alloc.cold.120+0x7b/0xdd
Thomas Bogendoerfer 776d31
 ? _cond_resched+0x15/0x30
Thomas Bogendoerfer 776d31
 ? __alloc_pages_direct_compact+0x15f/0x170
Thomas Bogendoerfer 776d31
 __alloc_pages_slowpath.constprop.108+0xc58/0xc70
Thomas Bogendoerfer 776d31
 __alloc_pages_nodemask+0x2d0/0x300
Thomas Bogendoerfer 776d31
 kmalloc_order+0x24/0xe0
Thomas Bogendoerfer 776d31
 kmalloc_order_trace+0x19/0x80
Thomas Bogendoerfer 776d31
 bnxt_alloc_mem+0x1150/0x15c0 [bnxt_en]
Thomas Bogendoerfer 776d31
 ? bnxt_get_func_stat_ctxs+0x13/0x60 [bnxt_en]
Thomas Bogendoerfer 776d31
 __bnxt_open_nic+0x12e/0x780 [bnxt_en]
Thomas Bogendoerfer 776d31
 bnxt_open+0x10b/0x240 [bnxt_en]
Thomas Bogendoerfer 776d31
 __dev_open+0xe9/0x180
Thomas Bogendoerfer 776d31
 __dev_change_flags+0x1af/0x220
Thomas Bogendoerfer 776d31
 dev_change_flags+0x21/0x60
Thomas Bogendoerfer 776d31
 do_setlink+0x35c/0x1100
Thomas Bogendoerfer 776d31
Thomas Bogendoerfer 776d31
Instead of allocating this big chunk of memory and dividing it up for the
Thomas Bogendoerfer 776d31
concurrent TPA instances, allocate each small chunk separately for each
Thomas Bogendoerfer 776d31
TPA instance.  This will reduce it to order-0 allocations.
Thomas Bogendoerfer 776d31
Thomas Bogendoerfer 776d31
Fixes: 79632e9ba386 ("bnxt_en: Expand bnxt_tpa_info struct to support 57500 chips.")
Thomas Bogendoerfer 776d31
Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
Thomas Bogendoerfer 776d31
Reviewed-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Thomas Bogendoerfer 776d31
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Thomas Bogendoerfer 776d31
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Thomas Bogendoerfer 776d31
Signed-off-by: David S. Miller <davem@davemloft.net>
Thomas Bogendoerfer 776d31
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer 776d31
---
Thomas Bogendoerfer 776d31
 drivers/net/ethernet/broadcom/bnxt/bnxt.c |   23 ++++++++++++-----------
Thomas Bogendoerfer 776d31
 1 file changed, 12 insertions(+), 11 deletions(-)
Thomas Bogendoerfer 776d31
Thomas Bogendoerfer 776d31
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
Thomas Bogendoerfer 776d31
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
Thomas Bogendoerfer 776d31
@@ -3143,7 +3143,7 @@ static int bnxt_alloc_ring(struct bnxt *
Thomas Bogendoerfer 776d31
 
Thomas Bogendoerfer 776d31
 static void bnxt_free_tpa_info(struct bnxt *bp)
Thomas Bogendoerfer 776d31
 {
Thomas Bogendoerfer 776d31
-	int i;
Thomas Bogendoerfer 776d31
+	int i, j;
Thomas Bogendoerfer 776d31
 
Thomas Bogendoerfer 776d31
 	for (i = 0; i < bp->rx_nr_rings; i++) {
Thomas Bogendoerfer 776d31
 		struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
Thomas Bogendoerfer 776d31
@@ -3151,8 +3151,10 @@ static void bnxt_free_tpa_info(struct bn
Thomas Bogendoerfer 776d31
 		kfree(rxr->rx_tpa_idx_map);
Thomas Bogendoerfer 776d31
 		rxr->rx_tpa_idx_map = NULL;
Thomas Bogendoerfer 776d31
 		if (rxr->rx_tpa) {
Thomas Bogendoerfer 776d31
-			kfree(rxr->rx_tpa[0].agg_arr);
Thomas Bogendoerfer 776d31
-			rxr->rx_tpa[0].agg_arr = NULL;
Thomas Bogendoerfer 776d31
+			for (j = 0; j < bp->max_tpa; j++) {
Thomas Bogendoerfer 776d31
+				kfree(rxr->rx_tpa[j].agg_arr);
Thomas Bogendoerfer 776d31
+				rxr->rx_tpa[j].agg_arr = NULL;
Thomas Bogendoerfer 776d31
+			}
Thomas Bogendoerfer 776d31
 		}
Thomas Bogendoerfer 776d31
 		kfree(rxr->rx_tpa);
Thomas Bogendoerfer 776d31
 		rxr->rx_tpa = NULL;
Thomas Bogendoerfer 776d31
@@ -3161,14 +3163,13 @@ static void bnxt_free_tpa_info(struct bn
Thomas Bogendoerfer 776d31
 
Thomas Bogendoerfer 776d31
 static int bnxt_alloc_tpa_info(struct bnxt *bp)
Thomas Bogendoerfer 776d31
 {
Thomas Bogendoerfer 776d31
-	int i, j, total_aggs = 0;
Thomas Bogendoerfer 776d31
+	int i, j;
Thomas Bogendoerfer 776d31
 
Thomas Bogendoerfer 776d31
 	bp->max_tpa = MAX_TPA;
Thomas Bogendoerfer 776d31
 	if (bp->flags & BNXT_FLAG_CHIP_P5) {
Thomas Bogendoerfer 776d31
 		if (!bp->max_tpa_v2)
Thomas Bogendoerfer 776d31
 			return 0;
Thomas Bogendoerfer 776d31
 		bp->max_tpa = max_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
Thomas Bogendoerfer 776d31
-		total_aggs = bp->max_tpa * MAX_SKB_FRAGS;
Thomas Bogendoerfer 776d31
 	}
Thomas Bogendoerfer 776d31
 
Thomas Bogendoerfer 776d31
 	for (i = 0; i < bp->rx_nr_rings; i++) {
Thomas Bogendoerfer 776d31
@@ -3182,12 +3183,12 @@ static int bnxt_alloc_tpa_info(struct bn
Thomas Bogendoerfer 776d31
 
Thomas Bogendoerfer 776d31
 		if (!(bp->flags & BNXT_FLAG_CHIP_P5))
Thomas Bogendoerfer 776d31
 			continue;
Thomas Bogendoerfer 776d31
-		agg = kcalloc(total_aggs, sizeof(*agg), GFP_KERNEL);
Thomas Bogendoerfer 776d31
-		rxr->rx_tpa[0].agg_arr = agg;
Thomas Bogendoerfer 776d31
-		if (!agg)
Thomas Bogendoerfer 776d31
-			return -ENOMEM;
Thomas Bogendoerfer 776d31
-		for (j = 1; j < bp->max_tpa; j++)
Thomas Bogendoerfer 776d31
-			rxr->rx_tpa[j].agg_arr = agg + j * MAX_SKB_FRAGS;
Thomas Bogendoerfer 776d31
+		for (j = 0; j < bp->max_tpa; j++) {
Thomas Bogendoerfer 776d31
+			agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL);
Thomas Bogendoerfer 776d31
+			if (!agg)
Thomas Bogendoerfer 776d31
+				return -ENOMEM;
Thomas Bogendoerfer 776d31
+			rxr->rx_tpa[j].agg_arr = agg;
Thomas Bogendoerfer 776d31
+		}
Thomas Bogendoerfer 776d31
 		rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map),
Thomas Bogendoerfer 776d31
 					      GFP_KERNEL);
Thomas Bogendoerfer 776d31
 		if (!rxr->rx_tpa_idx_map)