xref: /linux/drivers/net/ethernet/alibaba/eea/eea_tx.c (revision aa8bca4cf20027d5dd59a5de207ecb4720d910c8)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Driver for Alibaba Elastic Ethernet Adapter.
4  *
5  * Copyright (C) 2025 Alibaba Inc.
6  */
7 
8 #include <net/netdev_queues.h>
9 
10 #include "eea_net.h"
11 #include "eea_pci.h"
12 #include "eea_ring.h"
13 
14 struct eea_tx_meta {
15 	struct eea_tx_meta *next;
16 
17 	u32 id;
18 
19 	union {
20 		struct sk_buff *skb;
21 		void *data;
22 	};
23 
24 	u32 num;
25 
26 	dma_addr_t dma_addr;
27 	struct eea_tx_desc *desc;
28 	u32 dma_len;
29 };
30 
31 int eea_poll_tx(struct eea_net_tx *tx, int budget)
32 {
33 	/* Empty function; will be implemented in a subsequent commit. */
34 	return budget;
35 }
36 
37 netdev_tx_t eea_tx_xmit(struct sk_buff *skb, struct net_device *netdev)
38 {
39 	/* Empty function; will be implemented in a subsequent commit. */
40 	dev_kfree_skb_any(skb);
41 	return NETDEV_TX_OK;
42 }
43 
44 static void eea_free_meta(struct eea_net_tx *tx, struct eea_net_cfg *cfg)
45 {
46 	kvfree(tx->meta);
47 	tx->meta = NULL;
48 }
49 
50 /* Maybe called before eea_bind_q_and_cfg. So the cfg must be passed. */
51 void eea_free_tx(struct eea_net_tx *tx, struct eea_net_cfg *cfg)
52 {
53 	if (!tx)
54 		return;
55 
56 	if (tx->ering) {
57 		eea_ering_free(tx->ering);
58 		tx->ering = NULL;
59 	}
60 
61 	if (tx->meta)
62 		eea_free_meta(tx, cfg);
63 }
64 
65 int eea_alloc_tx(struct eea_net_init_ctx *ctx, struct eea_net_tx *tx, u32 idx)
66 {
67 	struct eea_tx_meta *meta;
68 	struct eea_ring *ering;
69 	u32 i;
70 
71 	snprintf(tx->name, sizeof(tx->name), "tx.%u", idx);
72 
73 	ering = eea_ering_alloc(idx * 2 + 1, ctx->cfg.tx_ring_depth, ctx->edev,
74 				ctx->cfg.tx_sq_desc_size,
75 				ctx->cfg.tx_cq_desc_size,
76 				tx->name);
77 	if (!ering)
78 		goto err_free_tx;
79 
80 	tx->ering = ering;
81 	tx->index = idx;
82 	tx->dma_dev = ctx->edev->dma_dev;
83 
84 	/* meta */
85 	tx->meta = kvcalloc(ctx->cfg.tx_ring_depth,
86 			    sizeof(*tx->meta), GFP_KERNEL);
87 	if (!tx->meta)
88 		goto err_free_tx;
89 
90 	for (i = 0; i < ctx->cfg.tx_ring_depth; ++i) {
91 		meta = &tx->meta[i];
92 		meta->id = i;
93 		meta->next = tx->free;
94 		tx->free = meta;
95 	}
96 
97 	return 0;
98 
99 err_free_tx:
100 	eea_free_tx(tx, &ctx->cfg);
101 	return -ENOMEM;
102 }
103