mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
net: mana: Use per-queue allocation for tx_qp to reduce allocation size
Convert tx_qp from a single contiguous array allocation to per-queue individual allocations. Each mana_tx_qp struct is approximately 35KB. With many queues (e.g., 32/64), the flat array requires a single contiguous allocation that can fail under memory fragmentation. Change mana_tx_qp *tx_qp to mana_tx_qp **tx_qp (array of pointers), allocating each queue's mana_tx_qp individually via kvzalloc. This reduces each allocation to ~35KB and provides vmalloc fallback, avoiding allocation failure due to fragmentation. Signed-off-by: Aditya Garg <gargaditya@linux.microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Link: https://patch.msgid.link/20260502074552.23857-2-gargaditya@linux.microsoft.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
561e066284
commit
d07efe5a6e
@@ -68,7 +68,7 @@ int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames,
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_stats = &apc->tx_qp[q_idx].txq.stats;
|
tx_stats = &apc->tx_qp[q_idx]->txq.stats;
|
||||||
|
|
||||||
u64_stats_update_begin(&tx_stats->syncp);
|
u64_stats_update_begin(&tx_stats->syncp);
|
||||||
tx_stats->xdp_xmit += count;
|
tx_stats->xdp_xmit += count;
|
||||||
|
|||||||
@@ -355,9 +355,9 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||||||
if (skb_cow_head(skb, MANA_HEADROOM))
|
if (skb_cow_head(skb, MANA_HEADROOM))
|
||||||
goto tx_drop_count;
|
goto tx_drop_count;
|
||||||
|
|
||||||
txq = &apc->tx_qp[txq_idx].txq;
|
txq = &apc->tx_qp[txq_idx]->txq;
|
||||||
gdma_sq = txq->gdma_sq;
|
gdma_sq = txq->gdma_sq;
|
||||||
cq = &apc->tx_qp[txq_idx].tx_cq;
|
cq = &apc->tx_qp[txq_idx]->tx_cq;
|
||||||
tx_stats = &txq->stats;
|
tx_stats = &txq->stats;
|
||||||
|
|
||||||
BUILD_BUG_ON(MAX_TX_WQE_SGL_ENTRIES != MANA_MAX_TX_WQE_SGL_ENTRIES);
|
BUILD_BUG_ON(MAX_TX_WQE_SGL_ENTRIES != MANA_MAX_TX_WQE_SGL_ENTRIES);
|
||||||
@@ -614,7 +614,7 @@ static void mana_get_stats64(struct net_device *ndev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (q = 0; q < num_queues; q++) {
|
for (q = 0; q < num_queues; q++) {
|
||||||
tx_stats = &apc->tx_qp[q].txq.stats;
|
tx_stats = &apc->tx_qp[q]->txq.stats;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
start = u64_stats_fetch_begin(&tx_stats->syncp);
|
start = u64_stats_fetch_begin(&tx_stats->syncp);
|
||||||
@@ -2327,21 +2327,26 @@ static void mana_destroy_txq(struct mana_port_context *apc)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < apc->num_queues; i++) {
|
for (i = 0; i < apc->num_queues; i++) {
|
||||||
debugfs_remove_recursive(apc->tx_qp[i].mana_tx_debugfs);
|
if (!apc->tx_qp[i])
|
||||||
apc->tx_qp[i].mana_tx_debugfs = NULL;
|
continue;
|
||||||
|
|
||||||
napi = &apc->tx_qp[i].tx_cq.napi;
|
debugfs_remove_recursive(apc->tx_qp[i]->mana_tx_debugfs);
|
||||||
if (apc->tx_qp[i].txq.napi_initialized) {
|
apc->tx_qp[i]->mana_tx_debugfs = NULL;
|
||||||
|
|
||||||
|
napi = &apc->tx_qp[i]->tx_cq.napi;
|
||||||
|
if (apc->tx_qp[i]->txq.napi_initialized) {
|
||||||
napi_synchronize(napi);
|
napi_synchronize(napi);
|
||||||
napi_disable_locked(napi);
|
napi_disable_locked(napi);
|
||||||
netif_napi_del_locked(napi);
|
netif_napi_del_locked(napi);
|
||||||
apc->tx_qp[i].txq.napi_initialized = false;
|
apc->tx_qp[i]->txq.napi_initialized = false;
|
||||||
}
|
}
|
||||||
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i].tx_object);
|
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i]->tx_object);
|
||||||
|
|
||||||
mana_deinit_cq(apc, &apc->tx_qp[i].tx_cq);
|
mana_deinit_cq(apc, &apc->tx_qp[i]->tx_cq);
|
||||||
|
|
||||||
mana_deinit_txq(apc, &apc->tx_qp[i].txq);
|
mana_deinit_txq(apc, &apc->tx_qp[i]->txq);
|
||||||
|
|
||||||
|
kvfree(apc->tx_qp[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(apc->tx_qp);
|
kfree(apc->tx_qp);
|
||||||
@@ -2350,7 +2355,7 @@ static void mana_destroy_txq(struct mana_port_context *apc)
|
|||||||
|
|
||||||
static void mana_create_txq_debugfs(struct mana_port_context *apc, int idx)
|
static void mana_create_txq_debugfs(struct mana_port_context *apc, int idx)
|
||||||
{
|
{
|
||||||
struct mana_tx_qp *tx_qp = &apc->tx_qp[idx];
|
struct mana_tx_qp *tx_qp = apc->tx_qp[idx];
|
||||||
char qnum[32];
|
char qnum[32];
|
||||||
|
|
||||||
sprintf(qnum, "TX-%d", idx);
|
sprintf(qnum, "TX-%d", idx);
|
||||||
@@ -2389,7 +2394,7 @@ static int mana_create_txq(struct mana_port_context *apc,
|
|||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
apc->tx_qp = kzalloc_objs(struct mana_tx_qp, apc->num_queues);
|
apc->tx_qp = kzalloc_objs(struct mana_tx_qp *, apc->num_queues);
|
||||||
if (!apc->tx_qp)
|
if (!apc->tx_qp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -2409,10 +2414,16 @@ static int mana_create_txq(struct mana_port_context *apc,
|
|||||||
gc = gd->gdma_context;
|
gc = gd->gdma_context;
|
||||||
|
|
||||||
for (i = 0; i < apc->num_queues; i++) {
|
for (i = 0; i < apc->num_queues; i++) {
|
||||||
apc->tx_qp[i].tx_object = INVALID_MANA_HANDLE;
|
apc->tx_qp[i] = kvzalloc_obj(*apc->tx_qp[i]);
|
||||||
|
if (!apc->tx_qp[i]) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
apc->tx_qp[i]->tx_object = INVALID_MANA_HANDLE;
|
||||||
|
|
||||||
/* Create SQ */
|
/* Create SQ */
|
||||||
txq = &apc->tx_qp[i].txq;
|
txq = &apc->tx_qp[i]->txq;
|
||||||
|
|
||||||
u64_stats_init(&txq->stats.syncp);
|
u64_stats_init(&txq->stats.syncp);
|
||||||
txq->ndev = net;
|
txq->ndev = net;
|
||||||
@@ -2430,7 +2441,7 @@ static int mana_create_txq(struct mana_port_context *apc,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Create SQ's CQ */
|
/* Create SQ's CQ */
|
||||||
cq = &apc->tx_qp[i].tx_cq;
|
cq = &apc->tx_qp[i]->tx_cq;
|
||||||
cq->type = MANA_CQ_TYPE_TX;
|
cq->type = MANA_CQ_TYPE_TX;
|
||||||
|
|
||||||
cq->txq = txq;
|
cq->txq = txq;
|
||||||
@@ -2459,7 +2470,7 @@ static int mana_create_txq(struct mana_port_context *apc,
|
|||||||
|
|
||||||
err = mana_create_wq_obj(apc, apc->port_handle, GDMA_SQ,
|
err = mana_create_wq_obj(apc, apc->port_handle, GDMA_SQ,
|
||||||
&wq_spec, &cq_spec,
|
&wq_spec, &cq_spec,
|
||||||
&apc->tx_qp[i].tx_object);
|
&apc->tx_qp[i]->tx_object);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -3294,7 +3305,7 @@ static int mana_dealloc_queues(struct net_device *ndev)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < apc->num_queues; i++) {
|
for (i = 0; i < apc->num_queues; i++) {
|
||||||
txq = &apc->tx_qp[i].txq;
|
txq = &apc->tx_qp[i]->txq;
|
||||||
tsleep = 1000;
|
tsleep = 1000;
|
||||||
while (atomic_read(&txq->pending_sends) > 0 &&
|
while (atomic_read(&txq->pending_sends) > 0 &&
|
||||||
time_before(jiffies, timeout)) {
|
time_before(jiffies, timeout)) {
|
||||||
@@ -3313,7 +3324,7 @@ static int mana_dealloc_queues(struct net_device *ndev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < apc->num_queues; i++) {
|
for (i = 0; i < apc->num_queues; i++) {
|
||||||
txq = &apc->tx_qp[i].txq;
|
txq = &apc->tx_qp[i]->txq;
|
||||||
while ((skb = skb_dequeue(&txq->pending_skbs))) {
|
while ((skb = skb_dequeue(&txq->pending_skbs))) {
|
||||||
mana_unmap_skb(skb, apc);
|
mana_unmap_skb(skb, apc);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (q = 0; q < num_queues; q++) {
|
for (q = 0; q < num_queues; q++) {
|
||||||
tx_stats = &apc->tx_qp[q].txq.stats;
|
tx_stats = &apc->tx_qp[q]->txq.stats;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
start = u64_stats_fetch_begin(&tx_stats->syncp);
|
start = u64_stats_fetch_begin(&tx_stats->syncp);
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ struct mana_port_context {
|
|||||||
bool tx_shortform_allowed;
|
bool tx_shortform_allowed;
|
||||||
u16 tx_vp_offset;
|
u16 tx_vp_offset;
|
||||||
|
|
||||||
struct mana_tx_qp *tx_qp;
|
struct mana_tx_qp **tx_qp;
|
||||||
|
|
||||||
/* Indirection Table for RX & TX. The values are queue indexes */
|
/* Indirection Table for RX & TX. The values are queue indexes */
|
||||||
u32 *indir_table;
|
u32 *indir_table;
|
||||||
|
|||||||
Reference in New Issue
Block a user