15e8c5adfSBailey Forrest // SPDX-License-Identifier: (GPL-2.0 OR MIT)
25e8c5adfSBailey Forrest /* Google virtual Ethernet (gve) driver
35e8c5adfSBailey Forrest *
45e8c5adfSBailey Forrest * Copyright (C) 2015-2021 Google, Inc.
55e8c5adfSBailey Forrest */
65e8c5adfSBailey Forrest
75e8c5adfSBailey Forrest #include "gve.h"
85e8c5adfSBailey Forrest #include "gve_adminq.h"
95e8c5adfSBailey Forrest #include "gve_utils.h"
105e8c5adfSBailey Forrest #include "gve_dqo.h"
11a695641cSCoco Li #include <net/ip.h>
125e8c5adfSBailey Forrest #include <linux/tcp.h>
135e8c5adfSBailey Forrest #include <linux/slab.h>
145e8c5adfSBailey Forrest #include <linux/skbuff.h>
155e8c5adfSBailey Forrest
16a6fb8d5aSRushil Gupta /* Returns true if tx_bufs are available. */
gve_has_free_tx_qpl_bufs(struct gve_tx_ring * tx,int count)17a6fb8d5aSRushil Gupta static bool gve_has_free_tx_qpl_bufs(struct gve_tx_ring *tx, int count)
18a6fb8d5aSRushil Gupta {
19a6fb8d5aSRushil Gupta int num_avail;
20a6fb8d5aSRushil Gupta
21a6fb8d5aSRushil Gupta if (!tx->dqo.qpl)
22a6fb8d5aSRushil Gupta return true;
23a6fb8d5aSRushil Gupta
24a6fb8d5aSRushil Gupta num_avail = tx->dqo.num_tx_qpl_bufs -
25a6fb8d5aSRushil Gupta (tx->dqo_tx.alloc_tx_qpl_buf_cnt -
26a6fb8d5aSRushil Gupta tx->dqo_tx.free_tx_qpl_buf_cnt);
27a6fb8d5aSRushil Gupta
28a6fb8d5aSRushil Gupta if (count <= num_avail)
29a6fb8d5aSRushil Gupta return true;
30a6fb8d5aSRushil Gupta
31a6fb8d5aSRushil Gupta /* Update cached value from dqo_compl. */
32a6fb8d5aSRushil Gupta tx->dqo_tx.free_tx_qpl_buf_cnt =
33a6fb8d5aSRushil Gupta atomic_read_acquire(&tx->dqo_compl.free_tx_qpl_buf_cnt);
34a6fb8d5aSRushil Gupta
35a6fb8d5aSRushil Gupta num_avail = tx->dqo.num_tx_qpl_bufs -
36a6fb8d5aSRushil Gupta (tx->dqo_tx.alloc_tx_qpl_buf_cnt -
37a6fb8d5aSRushil Gupta tx->dqo_tx.free_tx_qpl_buf_cnt);
38a6fb8d5aSRushil Gupta
39a6fb8d5aSRushil Gupta return count <= num_avail;
40a6fb8d5aSRushil Gupta }
41a6fb8d5aSRushil Gupta
42a6fb8d5aSRushil Gupta static s16
gve_alloc_tx_qpl_buf(struct gve_tx_ring * tx)43a6fb8d5aSRushil Gupta gve_alloc_tx_qpl_buf(struct gve_tx_ring *tx)
44a6fb8d5aSRushil Gupta {
45a6fb8d5aSRushil Gupta s16 index;
46a6fb8d5aSRushil Gupta
47a6fb8d5aSRushil Gupta index = tx->dqo_tx.free_tx_qpl_buf_head;
48a6fb8d5aSRushil Gupta
49a6fb8d5aSRushil Gupta /* No TX buffers available, try to steal the list from the
50a6fb8d5aSRushil Gupta * completion handler.
51a6fb8d5aSRushil Gupta */
52a6fb8d5aSRushil Gupta if (unlikely(index == -1)) {
53a6fb8d5aSRushil Gupta tx->dqo_tx.free_tx_qpl_buf_head =
54a6fb8d5aSRushil Gupta atomic_xchg(&tx->dqo_compl.free_tx_qpl_buf_head, -1);
55a6fb8d5aSRushil Gupta index = tx->dqo_tx.free_tx_qpl_buf_head;
56a6fb8d5aSRushil Gupta
57a6fb8d5aSRushil Gupta if (unlikely(index == -1))
58a6fb8d5aSRushil Gupta return index;
59a6fb8d5aSRushil Gupta }
60a6fb8d5aSRushil Gupta
61a6fb8d5aSRushil Gupta /* Remove TX buf from free list */
62a6fb8d5aSRushil Gupta tx->dqo_tx.free_tx_qpl_buf_head = tx->dqo.tx_qpl_buf_next[index];
63a6fb8d5aSRushil Gupta
64a6fb8d5aSRushil Gupta return index;
65a6fb8d5aSRushil Gupta }
66a6fb8d5aSRushil Gupta
67a6fb8d5aSRushil Gupta static void
gve_free_tx_qpl_bufs(struct gve_tx_ring * tx,struct gve_tx_pending_packet_dqo * pkt)68a6fb8d5aSRushil Gupta gve_free_tx_qpl_bufs(struct gve_tx_ring *tx,
69a6fb8d5aSRushil Gupta struct gve_tx_pending_packet_dqo *pkt)
70a6fb8d5aSRushil Gupta {
71a6fb8d5aSRushil Gupta s16 index;
72a6fb8d5aSRushil Gupta int i;
73a6fb8d5aSRushil Gupta
74a6fb8d5aSRushil Gupta if (!pkt->num_bufs)
75a6fb8d5aSRushil Gupta return;
76a6fb8d5aSRushil Gupta
77a6fb8d5aSRushil Gupta index = pkt->tx_qpl_buf_ids[0];
78a6fb8d5aSRushil Gupta /* Create a linked list of buffers to be added to the free list */
79a6fb8d5aSRushil Gupta for (i = 1; i < pkt->num_bufs; i++) {
80a6fb8d5aSRushil Gupta tx->dqo.tx_qpl_buf_next[index] = pkt->tx_qpl_buf_ids[i];
81a6fb8d5aSRushil Gupta index = pkt->tx_qpl_buf_ids[i];
82a6fb8d5aSRushil Gupta }
83a6fb8d5aSRushil Gupta
84a6fb8d5aSRushil Gupta while (true) {
85a6fb8d5aSRushil Gupta s16 old_head = atomic_read_acquire(&tx->dqo_compl.free_tx_qpl_buf_head);
86a6fb8d5aSRushil Gupta
87a6fb8d5aSRushil Gupta tx->dqo.tx_qpl_buf_next[index] = old_head;
88a6fb8d5aSRushil Gupta if (atomic_cmpxchg(&tx->dqo_compl.free_tx_qpl_buf_head,
89a6fb8d5aSRushil Gupta old_head,
90a6fb8d5aSRushil Gupta pkt->tx_qpl_buf_ids[0]) == old_head) {
91a6fb8d5aSRushil Gupta break;
92a6fb8d5aSRushil Gupta }
93a6fb8d5aSRushil Gupta }
94a6fb8d5aSRushil Gupta
95a6fb8d5aSRushil Gupta atomic_add(pkt->num_bufs, &tx->dqo_compl.free_tx_qpl_buf_cnt);
96a6fb8d5aSRushil Gupta pkt->num_bufs = 0;
97a6fb8d5aSRushil Gupta }
98a6fb8d5aSRushil Gupta
99a57e5de4SBailey Forrest /* Returns true if a gve_tx_pending_packet_dqo object is available. */
gve_has_pending_packet(struct gve_tx_ring * tx)100a57e5de4SBailey Forrest static bool gve_has_pending_packet(struct gve_tx_ring *tx)
101a57e5de4SBailey Forrest {
102a57e5de4SBailey Forrest /* Check TX path's list. */
103a57e5de4SBailey Forrest if (tx->dqo_tx.free_pending_packets != -1)
104a57e5de4SBailey Forrest return true;
105a57e5de4SBailey Forrest
106a57e5de4SBailey Forrest /* Check completion handler's list. */
107a57e5de4SBailey Forrest if (atomic_read_acquire(&tx->dqo_compl.free_pending_packets) != -1)
108a57e5de4SBailey Forrest return true;
109a57e5de4SBailey Forrest
110a57e5de4SBailey Forrest return false;
111a57e5de4SBailey Forrest }
112a57e5de4SBailey Forrest
113a57e5de4SBailey Forrest static struct gve_tx_pending_packet_dqo *
gve_alloc_pending_packet(struct gve_tx_ring * tx)114a57e5de4SBailey Forrest gve_alloc_pending_packet(struct gve_tx_ring *tx)
115a57e5de4SBailey Forrest {
116a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet;
117a57e5de4SBailey Forrest s16 index;
118a57e5de4SBailey Forrest
119a57e5de4SBailey Forrest index = tx->dqo_tx.free_pending_packets;
120a57e5de4SBailey Forrest
121a57e5de4SBailey Forrest /* No pending_packets available, try to steal the list from the
122a57e5de4SBailey Forrest * completion handler.
123a57e5de4SBailey Forrest */
124a57e5de4SBailey Forrest if (unlikely(index == -1)) {
125a57e5de4SBailey Forrest tx->dqo_tx.free_pending_packets =
126a57e5de4SBailey Forrest atomic_xchg(&tx->dqo_compl.free_pending_packets, -1);
127a57e5de4SBailey Forrest index = tx->dqo_tx.free_pending_packets;
128a57e5de4SBailey Forrest
129a57e5de4SBailey Forrest if (unlikely(index == -1))
130a57e5de4SBailey Forrest return NULL;
131a57e5de4SBailey Forrest }
132a57e5de4SBailey Forrest
133a57e5de4SBailey Forrest pending_packet = &tx->dqo.pending_packets[index];
134a57e5de4SBailey Forrest
135a57e5de4SBailey Forrest /* Remove pending_packet from free list */
136a57e5de4SBailey Forrest tx->dqo_tx.free_pending_packets = pending_packet->next;
137a57e5de4SBailey Forrest pending_packet->state = GVE_PACKET_STATE_PENDING_DATA_COMPL;
138a57e5de4SBailey Forrest
139a57e5de4SBailey Forrest return pending_packet;
140a57e5de4SBailey Forrest }
141a57e5de4SBailey Forrest
142a57e5de4SBailey Forrest static void
gve_free_pending_packet(struct gve_tx_ring * tx,struct gve_tx_pending_packet_dqo * pending_packet)143a57e5de4SBailey Forrest gve_free_pending_packet(struct gve_tx_ring *tx,
144a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet)
145a57e5de4SBailey Forrest {
146a57e5de4SBailey Forrest s16 index = pending_packet - tx->dqo.pending_packets;
147a57e5de4SBailey Forrest
148a57e5de4SBailey Forrest pending_packet->state = GVE_PACKET_STATE_UNALLOCATED;
149a57e5de4SBailey Forrest while (true) {
150a57e5de4SBailey Forrest s16 old_head = atomic_read_acquire(&tx->dqo_compl.free_pending_packets);
151a57e5de4SBailey Forrest
152a57e5de4SBailey Forrest pending_packet->next = old_head;
153a57e5de4SBailey Forrest if (atomic_cmpxchg(&tx->dqo_compl.free_pending_packets,
154a57e5de4SBailey Forrest old_head, index) == old_head) {
155a57e5de4SBailey Forrest break;
156a57e5de4SBailey Forrest }
157a57e5de4SBailey Forrest }
158a57e5de4SBailey Forrest }
159a57e5de4SBailey Forrest
1609c1a59a2SBailey Forrest /* gve_tx_free_desc - Cleans up all pending tx requests and buffers.
1619c1a59a2SBailey Forrest */
gve_tx_clean_pending_packets(struct gve_tx_ring * tx)1629c1a59a2SBailey Forrest static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx)
1639c1a59a2SBailey Forrest {
1649c1a59a2SBailey Forrest int i;
1659c1a59a2SBailey Forrest
1669c1a59a2SBailey Forrest for (i = 0; i < tx->dqo.num_pending_packets; i++) {
1679c1a59a2SBailey Forrest struct gve_tx_pending_packet_dqo *cur_state =
1689c1a59a2SBailey Forrest &tx->dqo.pending_packets[i];
1699c1a59a2SBailey Forrest int j;
1709c1a59a2SBailey Forrest
1719c1a59a2SBailey Forrest for (j = 0; j < cur_state->num_bufs; j++) {
1729c1a59a2SBailey Forrest if (j == 0) {
1739c1a59a2SBailey Forrest dma_unmap_single(tx->dev,
1741e0083bdSArnd Bergmann dma_unmap_addr(cur_state, dma[j]),
1751e0083bdSArnd Bergmann dma_unmap_len(cur_state, len[j]),
1769c1a59a2SBailey Forrest DMA_TO_DEVICE);
1779c1a59a2SBailey Forrest } else {
1789c1a59a2SBailey Forrest dma_unmap_page(tx->dev,
1791e0083bdSArnd Bergmann dma_unmap_addr(cur_state, dma[j]),
1801e0083bdSArnd Bergmann dma_unmap_len(cur_state, len[j]),
1819c1a59a2SBailey Forrest DMA_TO_DEVICE);
1829c1a59a2SBailey Forrest }
1839c1a59a2SBailey Forrest }
1849c1a59a2SBailey Forrest if (cur_state->skb) {
1859c1a59a2SBailey Forrest dev_consume_skb_any(cur_state->skb);
1869c1a59a2SBailey Forrest cur_state->skb = NULL;
1879c1a59a2SBailey Forrest }
1889c1a59a2SBailey Forrest }
1899c1a59a2SBailey Forrest }
1909c1a59a2SBailey Forrest
gve_tx_free_ring_dqo(struct gve_priv * priv,int idx)1919c1a59a2SBailey Forrest static void gve_tx_free_ring_dqo(struct gve_priv *priv, int idx)
1929c1a59a2SBailey Forrest {
1939c1a59a2SBailey Forrest struct gve_tx_ring *tx = &priv->tx[idx];
1949c1a59a2SBailey Forrest struct device *hdev = &priv->pdev->dev;
1959c1a59a2SBailey Forrest size_t bytes;
1969c1a59a2SBailey Forrest
1979c1a59a2SBailey Forrest gve_tx_remove_from_block(priv, idx);
1989c1a59a2SBailey Forrest
1999c1a59a2SBailey Forrest if (tx->q_resources) {
2009c1a59a2SBailey Forrest dma_free_coherent(hdev, sizeof(*tx->q_resources),
2019c1a59a2SBailey Forrest tx->q_resources, tx->q_resources_bus);
2029c1a59a2SBailey Forrest tx->q_resources = NULL;
2039c1a59a2SBailey Forrest }
2049c1a59a2SBailey Forrest
2059c1a59a2SBailey Forrest if (tx->dqo.compl_ring) {
2069c1a59a2SBailey Forrest bytes = sizeof(tx->dqo.compl_ring[0]) *
2079c1a59a2SBailey Forrest (tx->dqo.complq_mask + 1);
2089c1a59a2SBailey Forrest dma_free_coherent(hdev, bytes, tx->dqo.compl_ring,
2099c1a59a2SBailey Forrest tx->complq_bus_dqo);
2109c1a59a2SBailey Forrest tx->dqo.compl_ring = NULL;
2119c1a59a2SBailey Forrest }
2129c1a59a2SBailey Forrest
2139c1a59a2SBailey Forrest if (tx->dqo.tx_ring) {
2149c1a59a2SBailey Forrest bytes = sizeof(tx->dqo.tx_ring[0]) * (tx->mask + 1);
2159c1a59a2SBailey Forrest dma_free_coherent(hdev, bytes, tx->dqo.tx_ring, tx->bus);
2169c1a59a2SBailey Forrest tx->dqo.tx_ring = NULL;
2179c1a59a2SBailey Forrest }
2189c1a59a2SBailey Forrest
2199c1a59a2SBailey Forrest kvfree(tx->dqo.pending_packets);
2209c1a59a2SBailey Forrest tx->dqo.pending_packets = NULL;
2219c1a59a2SBailey Forrest
222a6fb8d5aSRushil Gupta kvfree(tx->dqo.tx_qpl_buf_next);
223a6fb8d5aSRushil Gupta tx->dqo.tx_qpl_buf_next = NULL;
224a6fb8d5aSRushil Gupta
225a6fb8d5aSRushil Gupta if (tx->dqo.qpl) {
226a6fb8d5aSRushil Gupta gve_unassign_qpl(priv, tx->dqo.qpl->id);
227a6fb8d5aSRushil Gupta tx->dqo.qpl = NULL;
228a6fb8d5aSRushil Gupta }
229a6fb8d5aSRushil Gupta
2309c1a59a2SBailey Forrest netif_dbg(priv, drv, priv->dev, "freed tx queue %d\n", idx);
2319c1a59a2SBailey Forrest }
2329c1a59a2SBailey Forrest
gve_tx_qpl_buf_init(struct gve_tx_ring * tx)233a6fb8d5aSRushil Gupta static int gve_tx_qpl_buf_init(struct gve_tx_ring *tx)
234a6fb8d5aSRushil Gupta {
235a6fb8d5aSRushil Gupta int num_tx_qpl_bufs = GVE_TX_BUFS_PER_PAGE_DQO *
236a6fb8d5aSRushil Gupta tx->dqo.qpl->num_entries;
237a6fb8d5aSRushil Gupta int i;
238a6fb8d5aSRushil Gupta
239a6fb8d5aSRushil Gupta tx->dqo.tx_qpl_buf_next = kvcalloc(num_tx_qpl_bufs,
240a6fb8d5aSRushil Gupta sizeof(tx->dqo.tx_qpl_buf_next[0]),
241a6fb8d5aSRushil Gupta GFP_KERNEL);
242a6fb8d5aSRushil Gupta if (!tx->dqo.tx_qpl_buf_next)
243a6fb8d5aSRushil Gupta return -ENOMEM;
244a6fb8d5aSRushil Gupta
245a6fb8d5aSRushil Gupta tx->dqo.num_tx_qpl_bufs = num_tx_qpl_bufs;
246a6fb8d5aSRushil Gupta
247a6fb8d5aSRushil Gupta /* Generate free TX buf list */
248a6fb8d5aSRushil Gupta for (i = 0; i < num_tx_qpl_bufs - 1; i++)
249a6fb8d5aSRushil Gupta tx->dqo.tx_qpl_buf_next[i] = i + 1;
250a6fb8d5aSRushil Gupta tx->dqo.tx_qpl_buf_next[num_tx_qpl_bufs - 1] = -1;
251a6fb8d5aSRushil Gupta
252a6fb8d5aSRushil Gupta atomic_set_release(&tx->dqo_compl.free_tx_qpl_buf_head, -1);
253a6fb8d5aSRushil Gupta return 0;
254a6fb8d5aSRushil Gupta }
255a6fb8d5aSRushil Gupta
gve_tx_alloc_ring_dqo(struct gve_priv * priv,int idx)2569c1a59a2SBailey Forrest static int gve_tx_alloc_ring_dqo(struct gve_priv *priv, int idx)
2579c1a59a2SBailey Forrest {
2589c1a59a2SBailey Forrest struct gve_tx_ring *tx = &priv->tx[idx];
2599c1a59a2SBailey Forrest struct device *hdev = &priv->pdev->dev;
2609c1a59a2SBailey Forrest int num_pending_packets;
2619c1a59a2SBailey Forrest size_t bytes;
2629c1a59a2SBailey Forrest int i;
2639c1a59a2SBailey Forrest
2649c1a59a2SBailey Forrest memset(tx, 0, sizeof(*tx));
2659c1a59a2SBailey Forrest tx->q_num = idx;
2669c1a59a2SBailey Forrest tx->dev = &priv->pdev->dev;
2679c1a59a2SBailey Forrest tx->netdev_txq = netdev_get_tx_queue(priv->dev, idx);
2689c1a59a2SBailey Forrest atomic_set_release(&tx->dqo_compl.hw_tx_head, 0);
2699c1a59a2SBailey Forrest
2709c1a59a2SBailey Forrest /* Queue sizes must be a power of 2 */
2719c1a59a2SBailey Forrest tx->mask = priv->tx_desc_cnt - 1;
272a6fb8d5aSRushil Gupta tx->dqo.complq_mask = priv->queue_format == GVE_DQO_RDA_FORMAT ?
273a6fb8d5aSRushil Gupta priv->options_dqo_rda.tx_comp_ring_entries - 1 :
274a6fb8d5aSRushil Gupta tx->mask;
2759c1a59a2SBailey Forrest
2769c1a59a2SBailey Forrest /* The max number of pending packets determines the maximum number of
2779c1a59a2SBailey Forrest * descriptors which maybe written to the completion queue.
2789c1a59a2SBailey Forrest *
2799c1a59a2SBailey Forrest * We must set the number small enough to make sure we never overrun the
2809c1a59a2SBailey Forrest * completion queue.
2819c1a59a2SBailey Forrest */
2829c1a59a2SBailey Forrest num_pending_packets = tx->dqo.complq_mask + 1;
2839c1a59a2SBailey Forrest
2849c1a59a2SBailey Forrest /* Reserve space for descriptor completions, which will be reported at
2859c1a59a2SBailey Forrest * most every GVE_TX_MIN_RE_INTERVAL packets.
2869c1a59a2SBailey Forrest */
2879c1a59a2SBailey Forrest num_pending_packets -=
2889c1a59a2SBailey Forrest (tx->dqo.complq_mask + 1) / GVE_TX_MIN_RE_INTERVAL;
2899c1a59a2SBailey Forrest
2909c1a59a2SBailey Forrest /* Each packet may have at most 2 buffer completions if it receives both
2919c1a59a2SBailey Forrest * a miss and reinjection completion.
2929c1a59a2SBailey Forrest */
2939c1a59a2SBailey Forrest num_pending_packets /= 2;
2949c1a59a2SBailey Forrest
2959c1a59a2SBailey Forrest tx->dqo.num_pending_packets = min_t(int, num_pending_packets, S16_MAX);
2969c1a59a2SBailey Forrest tx->dqo.pending_packets = kvcalloc(tx->dqo.num_pending_packets,
2979c1a59a2SBailey Forrest sizeof(tx->dqo.pending_packets[0]),
2989c1a59a2SBailey Forrest GFP_KERNEL);
2999c1a59a2SBailey Forrest if (!tx->dqo.pending_packets)
3009c1a59a2SBailey Forrest goto err;
3019c1a59a2SBailey Forrest
3029c1a59a2SBailey Forrest /* Set up linked list of pending packets */
3039c1a59a2SBailey Forrest for (i = 0; i < tx->dqo.num_pending_packets - 1; i++)
3049c1a59a2SBailey Forrest tx->dqo.pending_packets[i].next = i + 1;
3059c1a59a2SBailey Forrest
3069c1a59a2SBailey Forrest tx->dqo.pending_packets[tx->dqo.num_pending_packets - 1].next = -1;
3079c1a59a2SBailey Forrest atomic_set_release(&tx->dqo_compl.free_pending_packets, -1);
3089c1a59a2SBailey Forrest tx->dqo_compl.miss_completions.head = -1;
3099c1a59a2SBailey Forrest tx->dqo_compl.miss_completions.tail = -1;
3109c1a59a2SBailey Forrest tx->dqo_compl.timed_out_completions.head = -1;
3119c1a59a2SBailey Forrest tx->dqo_compl.timed_out_completions.tail = -1;
3129c1a59a2SBailey Forrest
3139c1a59a2SBailey Forrest bytes = sizeof(tx->dqo.tx_ring[0]) * (tx->mask + 1);
3149c1a59a2SBailey Forrest tx->dqo.tx_ring = dma_alloc_coherent(hdev, bytes, &tx->bus, GFP_KERNEL);
3159c1a59a2SBailey Forrest if (!tx->dqo.tx_ring)
3169c1a59a2SBailey Forrest goto err;
3179c1a59a2SBailey Forrest
3189c1a59a2SBailey Forrest bytes = sizeof(tx->dqo.compl_ring[0]) * (tx->dqo.complq_mask + 1);
3199c1a59a2SBailey Forrest tx->dqo.compl_ring = dma_alloc_coherent(hdev, bytes,
3209c1a59a2SBailey Forrest &tx->complq_bus_dqo,
3219c1a59a2SBailey Forrest GFP_KERNEL);
3229c1a59a2SBailey Forrest if (!tx->dqo.compl_ring)
3239c1a59a2SBailey Forrest goto err;
3249c1a59a2SBailey Forrest
3259c1a59a2SBailey Forrest tx->q_resources = dma_alloc_coherent(hdev, sizeof(*tx->q_resources),
3269c1a59a2SBailey Forrest &tx->q_resources_bus, GFP_KERNEL);
3279c1a59a2SBailey Forrest if (!tx->q_resources)
3289c1a59a2SBailey Forrest goto err;
3299c1a59a2SBailey Forrest
330a6fb8d5aSRushil Gupta if (gve_is_qpl(priv)) {
331a6fb8d5aSRushil Gupta tx->dqo.qpl = gve_assign_tx_qpl(priv, idx);
332a6fb8d5aSRushil Gupta if (!tx->dqo.qpl)
333a6fb8d5aSRushil Gupta goto err;
334a6fb8d5aSRushil Gupta
335a6fb8d5aSRushil Gupta if (gve_tx_qpl_buf_init(tx))
336a6fb8d5aSRushil Gupta goto err;
337a6fb8d5aSRushil Gupta }
338a6fb8d5aSRushil Gupta
3399c1a59a2SBailey Forrest gve_tx_add_to_block(priv, idx);
3409c1a59a2SBailey Forrest
3419c1a59a2SBailey Forrest return 0;
3429c1a59a2SBailey Forrest
3439c1a59a2SBailey Forrest err:
3449c1a59a2SBailey Forrest gve_tx_free_ring_dqo(priv, idx);
3459c1a59a2SBailey Forrest return -ENOMEM;
3469c1a59a2SBailey Forrest }
3479c1a59a2SBailey Forrest
gve_tx_alloc_rings_dqo(struct gve_priv * priv)3489c1a59a2SBailey Forrest int gve_tx_alloc_rings_dqo(struct gve_priv *priv)
3499c1a59a2SBailey Forrest {
3509c1a59a2SBailey Forrest int err = 0;
3519c1a59a2SBailey Forrest int i;
3529c1a59a2SBailey Forrest
3539c1a59a2SBailey Forrest for (i = 0; i < priv->tx_cfg.num_queues; i++) {
3549c1a59a2SBailey Forrest err = gve_tx_alloc_ring_dqo(priv, i);
3559c1a59a2SBailey Forrest if (err) {
3569c1a59a2SBailey Forrest netif_err(priv, drv, priv->dev,
3579c1a59a2SBailey Forrest "Failed to alloc tx ring=%d: err=%d\n",
3589c1a59a2SBailey Forrest i, err);
3599c1a59a2SBailey Forrest goto err;
3609c1a59a2SBailey Forrest }
3619c1a59a2SBailey Forrest }
3629c1a59a2SBailey Forrest
3639c1a59a2SBailey Forrest return 0;
3649c1a59a2SBailey Forrest
3659c1a59a2SBailey Forrest err:
3669c1a59a2SBailey Forrest for (i--; i >= 0; i--)
3679c1a59a2SBailey Forrest gve_tx_free_ring_dqo(priv, i);
3689c1a59a2SBailey Forrest
3699c1a59a2SBailey Forrest return err;
3709c1a59a2SBailey Forrest }
3719c1a59a2SBailey Forrest
gve_tx_free_rings_dqo(struct gve_priv * priv)3729c1a59a2SBailey Forrest void gve_tx_free_rings_dqo(struct gve_priv *priv)
3739c1a59a2SBailey Forrest {
3749c1a59a2SBailey Forrest int i;
3759c1a59a2SBailey Forrest
3769c1a59a2SBailey Forrest for (i = 0; i < priv->tx_cfg.num_queues; i++) {
3779c1a59a2SBailey Forrest struct gve_tx_ring *tx = &priv->tx[i];
3789c1a59a2SBailey Forrest
3799c1a59a2SBailey Forrest gve_clean_tx_done_dqo(priv, tx, /*napi=*/NULL);
3809c1a59a2SBailey Forrest netdev_tx_reset_queue(tx->netdev_txq);
3819c1a59a2SBailey Forrest gve_tx_clean_pending_packets(tx);
3829c1a59a2SBailey Forrest
3839c1a59a2SBailey Forrest gve_tx_free_ring_dqo(priv, i);
3849c1a59a2SBailey Forrest }
3859c1a59a2SBailey Forrest }
3869c1a59a2SBailey Forrest
387a57e5de4SBailey Forrest /* Returns the number of slots available in the ring */
num_avail_tx_slots(const struct gve_tx_ring * tx)388e8192476SBailey Forrest static u32 num_avail_tx_slots(const struct gve_tx_ring *tx)
389a57e5de4SBailey Forrest {
390a57e5de4SBailey Forrest u32 num_used = (tx->dqo_tx.tail - tx->dqo_tx.head) & tx->mask;
391a57e5de4SBailey Forrest
392a57e5de4SBailey Forrest return tx->mask - num_used;
393a57e5de4SBailey Forrest }
394a57e5de4SBailey Forrest
gve_has_avail_slots_tx_dqo(struct gve_tx_ring * tx,int desc_count,int buf_count)395a6fb8d5aSRushil Gupta static bool gve_has_avail_slots_tx_dqo(struct gve_tx_ring *tx,
396a6fb8d5aSRushil Gupta int desc_count, int buf_count)
397a6fb8d5aSRushil Gupta {
398a6fb8d5aSRushil Gupta return gve_has_pending_packet(tx) &&
399a6fb8d5aSRushil Gupta num_avail_tx_slots(tx) >= desc_count &&
400a6fb8d5aSRushil Gupta gve_has_free_tx_qpl_bufs(tx, buf_count);
401a6fb8d5aSRushil Gupta }
402a6fb8d5aSRushil Gupta
403a57e5de4SBailey Forrest /* Stops the queue if available descriptors is less than 'count'.
404a57e5de4SBailey Forrest * Return: 0 if stop is not required.
405a57e5de4SBailey Forrest */
gve_maybe_stop_tx_dqo(struct gve_tx_ring * tx,int desc_count,int buf_count)406a6fb8d5aSRushil Gupta static int gve_maybe_stop_tx_dqo(struct gve_tx_ring *tx,
407a6fb8d5aSRushil Gupta int desc_count, int buf_count)
408a57e5de4SBailey Forrest {
409a6fb8d5aSRushil Gupta if (likely(gve_has_avail_slots_tx_dqo(tx, desc_count, buf_count)))
410a57e5de4SBailey Forrest return 0;
411a57e5de4SBailey Forrest
412a57e5de4SBailey Forrest /* Update cached TX head pointer */
413a57e5de4SBailey Forrest tx->dqo_tx.head = atomic_read_acquire(&tx->dqo_compl.hw_tx_head);
414a57e5de4SBailey Forrest
415a6fb8d5aSRushil Gupta if (likely(gve_has_avail_slots_tx_dqo(tx, desc_count, buf_count)))
416a57e5de4SBailey Forrest return 0;
417a57e5de4SBailey Forrest
418a57e5de4SBailey Forrest /* No space, so stop the queue */
419a57e5de4SBailey Forrest tx->stop_queue++;
420a57e5de4SBailey Forrest netif_tx_stop_queue(tx->netdev_txq);
421a57e5de4SBailey Forrest
422a57e5de4SBailey Forrest /* Sync with restarting queue in `gve_tx_poll_dqo()` */
423a57e5de4SBailey Forrest mb();
424a57e5de4SBailey Forrest
425a57e5de4SBailey Forrest /* After stopping queue, check if we can transmit again in order to
426a57e5de4SBailey Forrest * avoid TOCTOU bug.
427a57e5de4SBailey Forrest */
428a57e5de4SBailey Forrest tx->dqo_tx.head = atomic_read_acquire(&tx->dqo_compl.hw_tx_head);
429a57e5de4SBailey Forrest
430a6fb8d5aSRushil Gupta if (likely(!gve_has_avail_slots_tx_dqo(tx, desc_count, buf_count)))
431a57e5de4SBailey Forrest return -EBUSY;
432a57e5de4SBailey Forrest
433a57e5de4SBailey Forrest netif_tx_start_queue(tx->netdev_txq);
434a57e5de4SBailey Forrest tx->wake_queue++;
435a57e5de4SBailey Forrest return 0;
436a57e5de4SBailey Forrest }
437a57e5de4SBailey Forrest
gve_extract_tx_metadata_dqo(const struct sk_buff * skb,struct gve_tx_metadata_dqo * metadata)438a57e5de4SBailey Forrest static void gve_extract_tx_metadata_dqo(const struct sk_buff *skb,
439a57e5de4SBailey Forrest struct gve_tx_metadata_dqo *metadata)
440a57e5de4SBailey Forrest {
441a57e5de4SBailey Forrest memset(metadata, 0, sizeof(*metadata));
442a57e5de4SBailey Forrest metadata->version = GVE_TX_METADATA_VERSION_DQO;
443a57e5de4SBailey Forrest
444a57e5de4SBailey Forrest if (skb->l4_hash) {
445a57e5de4SBailey Forrest u16 path_hash = skb->hash ^ (skb->hash >> 16);
446a57e5de4SBailey Forrest
447a57e5de4SBailey Forrest path_hash &= (1 << 15) - 1;
448a57e5de4SBailey Forrest if (unlikely(path_hash == 0))
449a57e5de4SBailey Forrest path_hash = ~path_hash;
450a57e5de4SBailey Forrest
451a57e5de4SBailey Forrest metadata->path_hash = path_hash;
452a57e5de4SBailey Forrest }
453a57e5de4SBailey Forrest }
454a57e5de4SBailey Forrest
gve_tx_fill_pkt_desc_dqo(struct gve_tx_ring * tx,u32 * desc_idx,struct sk_buff * skb,u32 len,u64 addr,s16 compl_tag,bool eop,bool is_gso)455a57e5de4SBailey Forrest static void gve_tx_fill_pkt_desc_dqo(struct gve_tx_ring *tx, u32 *desc_idx,
456a57e5de4SBailey Forrest struct sk_buff *skb, u32 len, u64 addr,
457a57e5de4SBailey Forrest s16 compl_tag, bool eop, bool is_gso)
458a57e5de4SBailey Forrest {
459a57e5de4SBailey Forrest const bool checksum_offload_en = skb->ip_summed == CHECKSUM_PARTIAL;
460a57e5de4SBailey Forrest
461a57e5de4SBailey Forrest while (len > 0) {
462a57e5de4SBailey Forrest struct gve_tx_pkt_desc_dqo *desc =
463a57e5de4SBailey Forrest &tx->dqo.tx_ring[*desc_idx].pkt;
464a57e5de4SBailey Forrest u32 cur_len = min_t(u32, len, GVE_TX_MAX_BUF_SIZE_DQO);
465a57e5de4SBailey Forrest bool cur_eop = eop && cur_len == len;
466a57e5de4SBailey Forrest
467a57e5de4SBailey Forrest *desc = (struct gve_tx_pkt_desc_dqo){
468a57e5de4SBailey Forrest .buf_addr = cpu_to_le64(addr),
469a57e5de4SBailey Forrest .dtype = GVE_TX_PKT_DESC_DTYPE_DQO,
470a57e5de4SBailey Forrest .end_of_packet = cur_eop,
471a57e5de4SBailey Forrest .checksum_offload_enable = checksum_offload_en,
472a57e5de4SBailey Forrest .compl_tag = cpu_to_le16(compl_tag),
473a57e5de4SBailey Forrest .buf_size = cur_len,
474a57e5de4SBailey Forrest };
475a57e5de4SBailey Forrest
476a57e5de4SBailey Forrest addr += cur_len;
477a57e5de4SBailey Forrest len -= cur_len;
478a57e5de4SBailey Forrest *desc_idx = (*desc_idx + 1) & tx->mask;
479a57e5de4SBailey Forrest }
480a57e5de4SBailey Forrest }
481a57e5de4SBailey Forrest
482a57e5de4SBailey Forrest /* Validates and prepares `skb` for TSO.
483a57e5de4SBailey Forrest *
484a57e5de4SBailey Forrest * Returns header length, or < 0 if invalid.
485a57e5de4SBailey Forrest */
gve_prep_tso(struct sk_buff * skb)486a57e5de4SBailey Forrest static int gve_prep_tso(struct sk_buff *skb)
487a57e5de4SBailey Forrest {
488a57e5de4SBailey Forrest struct tcphdr *tcp;
489a57e5de4SBailey Forrest int header_len;
490a57e5de4SBailey Forrest u32 paylen;
491a57e5de4SBailey Forrest int err;
492a57e5de4SBailey Forrest
493a57e5de4SBailey Forrest /* Note: HW requires MSS (gso_size) to be <= 9728 and the total length
494a57e5de4SBailey Forrest * of the TSO to be <= 262143.
495a57e5de4SBailey Forrest *
496a57e5de4SBailey Forrest * However, we don't validate these because:
497a57e5de4SBailey Forrest * - Hypervisor enforces a limit of 9K MTU
498a57e5de4SBailey Forrest * - Kernel will not produce a TSO larger than 64k
499a57e5de4SBailey Forrest */
500a57e5de4SBailey Forrest
501a57e5de4SBailey Forrest if (unlikely(skb_shinfo(skb)->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
502a57e5de4SBailey Forrest return -1;
503a57e5de4SBailey Forrest
504d01f39f7SJoshua Washington if (!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
505d01f39f7SJoshua Washington return -EINVAL;
506d01f39f7SJoshua Washington
507a57e5de4SBailey Forrest /* Needed because we will modify header. */
508a57e5de4SBailey Forrest err = skb_cow_head(skb, 0);
509a57e5de4SBailey Forrest if (err < 0)
510a57e5de4SBailey Forrest return err;
511a57e5de4SBailey Forrest
512a57e5de4SBailey Forrest tcp = tcp_hdr(skb);
513a57e5de4SBailey Forrest paylen = skb->len - skb_transport_offset(skb);
514d01f39f7SJoshua Washington csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen));
515504148feSEric Dumazet header_len = skb_tcp_all_headers(skb);
516a57e5de4SBailey Forrest
517a57e5de4SBailey Forrest if (unlikely(header_len > GVE_TX_MAX_HDR_SIZE_DQO))
518a57e5de4SBailey Forrest return -EINVAL;
519a57e5de4SBailey Forrest
520a57e5de4SBailey Forrest return header_len;
521a57e5de4SBailey Forrest }
522a57e5de4SBailey Forrest
gve_tx_fill_tso_ctx_desc(struct gve_tx_tso_context_desc_dqo * desc,const struct sk_buff * skb,const struct gve_tx_metadata_dqo * metadata,int header_len)523a57e5de4SBailey Forrest static void gve_tx_fill_tso_ctx_desc(struct gve_tx_tso_context_desc_dqo *desc,
524a57e5de4SBailey Forrest const struct sk_buff *skb,
525a57e5de4SBailey Forrest const struct gve_tx_metadata_dqo *metadata,
526a57e5de4SBailey Forrest int header_len)
527a57e5de4SBailey Forrest {
528a57e5de4SBailey Forrest *desc = (struct gve_tx_tso_context_desc_dqo){
529a57e5de4SBailey Forrest .header_len = header_len,
530a57e5de4SBailey Forrest .cmd_dtype = {
531a57e5de4SBailey Forrest .dtype = GVE_TX_TSO_CTX_DESC_DTYPE_DQO,
532a57e5de4SBailey Forrest .tso = 1,
533a57e5de4SBailey Forrest },
534a57e5de4SBailey Forrest .flex0 = metadata->bytes[0],
535a57e5de4SBailey Forrest .flex5 = metadata->bytes[5],
536a57e5de4SBailey Forrest .flex6 = metadata->bytes[6],
537a57e5de4SBailey Forrest .flex7 = metadata->bytes[7],
538a57e5de4SBailey Forrest .flex8 = metadata->bytes[8],
539a57e5de4SBailey Forrest .flex9 = metadata->bytes[9],
540a57e5de4SBailey Forrest .flex10 = metadata->bytes[10],
541a57e5de4SBailey Forrest .flex11 = metadata->bytes[11],
542a57e5de4SBailey Forrest };
543a57e5de4SBailey Forrest desc->tso_total_len = skb->len - header_len;
544a57e5de4SBailey Forrest desc->mss = skb_shinfo(skb)->gso_size;
545a57e5de4SBailey Forrest }
546a57e5de4SBailey Forrest
547a57e5de4SBailey Forrest static void
gve_tx_fill_general_ctx_desc(struct gve_tx_general_context_desc_dqo * desc,const struct gve_tx_metadata_dqo * metadata)548a57e5de4SBailey Forrest gve_tx_fill_general_ctx_desc(struct gve_tx_general_context_desc_dqo *desc,
549a57e5de4SBailey Forrest const struct gve_tx_metadata_dqo *metadata)
550a57e5de4SBailey Forrest {
551a57e5de4SBailey Forrest *desc = (struct gve_tx_general_context_desc_dqo){
552a57e5de4SBailey Forrest .flex0 = metadata->bytes[0],
553a57e5de4SBailey Forrest .flex1 = metadata->bytes[1],
554a57e5de4SBailey Forrest .flex2 = metadata->bytes[2],
555a57e5de4SBailey Forrest .flex3 = metadata->bytes[3],
556a57e5de4SBailey Forrest .flex4 = metadata->bytes[4],
557a57e5de4SBailey Forrest .flex5 = metadata->bytes[5],
558a57e5de4SBailey Forrest .flex6 = metadata->bytes[6],
559a57e5de4SBailey Forrest .flex7 = metadata->bytes[7],
560a57e5de4SBailey Forrest .flex8 = metadata->bytes[8],
561a57e5de4SBailey Forrest .flex9 = metadata->bytes[9],
562a57e5de4SBailey Forrest .flex10 = metadata->bytes[10],
563a57e5de4SBailey Forrest .flex11 = metadata->bytes[11],
564a57e5de4SBailey Forrest .cmd_dtype = {.dtype = GVE_TX_GENERAL_CTX_DESC_DTYPE_DQO},
565a57e5de4SBailey Forrest };
566a57e5de4SBailey Forrest }
567a57e5de4SBailey Forrest
gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring * tx,struct sk_buff * skb,struct gve_tx_pending_packet_dqo * pkt,s16 completion_tag,u32 * desc_idx,bool is_gso)568a57e5de4SBailey Forrest static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx,
569a6fb8d5aSRushil Gupta struct sk_buff *skb,
570a6fb8d5aSRushil Gupta struct gve_tx_pending_packet_dqo *pkt,
571a6fb8d5aSRushil Gupta s16 completion_tag,
572a6fb8d5aSRushil Gupta u32 *desc_idx,
573a6fb8d5aSRushil Gupta bool is_gso)
574a57e5de4SBailey Forrest {
575a57e5de4SBailey Forrest const struct skb_shared_info *shinfo = skb_shinfo(skb);
576a57e5de4SBailey Forrest int i;
577a57e5de4SBailey Forrest
578a57e5de4SBailey Forrest /* Note: HW requires that the size of a non-TSO packet be within the
579a57e5de4SBailey Forrest * range of [17, 9728].
580a57e5de4SBailey Forrest *
581a57e5de4SBailey Forrest * We don't double check because
582a57e5de4SBailey Forrest * - We limited `netdev->min_mtu` to ETH_MIN_MTU.
583a57e5de4SBailey Forrest * - Hypervisor won't allow MTU larger than 9216.
584a57e5de4SBailey Forrest */
585a57e5de4SBailey Forrest
586a6fb8d5aSRushil Gupta pkt->num_bufs = 0;
587a57e5de4SBailey Forrest /* Map the linear portion of skb */
588a57e5de4SBailey Forrest {
589a57e5de4SBailey Forrest u32 len = skb_headlen(skb);
590a57e5de4SBailey Forrest dma_addr_t addr;
591a57e5de4SBailey Forrest
592a57e5de4SBailey Forrest addr = dma_map_single(tx->dev, skb->data, len, DMA_TO_DEVICE);
593a57e5de4SBailey Forrest if (unlikely(dma_mapping_error(tx->dev, addr)))
594a57e5de4SBailey Forrest goto err;
595a57e5de4SBailey Forrest
5961e0083bdSArnd Bergmann dma_unmap_len_set(pkt, len[pkt->num_bufs], len);
5971e0083bdSArnd Bergmann dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr);
5981e0083bdSArnd Bergmann ++pkt->num_bufs;
599a57e5de4SBailey Forrest
600a6fb8d5aSRushil Gupta gve_tx_fill_pkt_desc_dqo(tx, desc_idx, skb, len, addr,
601a57e5de4SBailey Forrest completion_tag,
602a57e5de4SBailey Forrest /*eop=*/shinfo->nr_frags == 0, is_gso);
603a57e5de4SBailey Forrest }
604a57e5de4SBailey Forrest
605a57e5de4SBailey Forrest for (i = 0; i < shinfo->nr_frags; i++) {
606a57e5de4SBailey Forrest const skb_frag_t *frag = &shinfo->frags[i];
607a57e5de4SBailey Forrest bool is_eop = i == (shinfo->nr_frags - 1);
608a57e5de4SBailey Forrest u32 len = skb_frag_size(frag);
609a57e5de4SBailey Forrest dma_addr_t addr;
610a57e5de4SBailey Forrest
611a57e5de4SBailey Forrest addr = skb_frag_dma_map(tx->dev, frag, 0, len, DMA_TO_DEVICE);
612a57e5de4SBailey Forrest if (unlikely(dma_mapping_error(tx->dev, addr)))
613a57e5de4SBailey Forrest goto err;
614a57e5de4SBailey Forrest
6151e0083bdSArnd Bergmann dma_unmap_len_set(pkt, len[pkt->num_bufs], len);
6161e0083bdSArnd Bergmann dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr);
6171e0083bdSArnd Bergmann ++pkt->num_bufs;
618a57e5de4SBailey Forrest
619a6fb8d5aSRushil Gupta gve_tx_fill_pkt_desc_dqo(tx, desc_idx, skb, len, addr,
620a57e5de4SBailey Forrest completion_tag, is_eop, is_gso);
621a57e5de4SBailey Forrest }
622a57e5de4SBailey Forrest
623a6fb8d5aSRushil Gupta return 0;
624a6fb8d5aSRushil Gupta err:
625a6fb8d5aSRushil Gupta for (i = 0; i < pkt->num_bufs; i++) {
626a6fb8d5aSRushil Gupta if (i == 0) {
627a6fb8d5aSRushil Gupta dma_unmap_single(tx->dev,
628a6fb8d5aSRushil Gupta dma_unmap_addr(pkt, dma[i]),
629a6fb8d5aSRushil Gupta dma_unmap_len(pkt, len[i]),
630a6fb8d5aSRushil Gupta DMA_TO_DEVICE);
631a6fb8d5aSRushil Gupta } else {
632a6fb8d5aSRushil Gupta dma_unmap_page(tx->dev,
633a6fb8d5aSRushil Gupta dma_unmap_addr(pkt, dma[i]),
634a6fb8d5aSRushil Gupta dma_unmap_len(pkt, len[i]),
635a6fb8d5aSRushil Gupta DMA_TO_DEVICE);
636a6fb8d5aSRushil Gupta }
637a6fb8d5aSRushil Gupta }
638a6fb8d5aSRushil Gupta pkt->num_bufs = 0;
639a6fb8d5aSRushil Gupta return -1;
640a6fb8d5aSRushil Gupta }
641a6fb8d5aSRushil Gupta
642a6fb8d5aSRushil Gupta /* Tx buffer i corresponds to
643a6fb8d5aSRushil Gupta * qpl_page_id = i / GVE_TX_BUFS_PER_PAGE_DQO
644a6fb8d5aSRushil Gupta * qpl_page_offset = (i % GVE_TX_BUFS_PER_PAGE_DQO) * GVE_TX_BUF_SIZE_DQO
645a6fb8d5aSRushil Gupta */
gve_tx_buf_get_addr(struct gve_tx_ring * tx,s16 index,void ** va,dma_addr_t * dma_addr)646a6fb8d5aSRushil Gupta static void gve_tx_buf_get_addr(struct gve_tx_ring *tx,
647a6fb8d5aSRushil Gupta s16 index,
648a6fb8d5aSRushil Gupta void **va, dma_addr_t *dma_addr)
649a6fb8d5aSRushil Gupta {
650a6fb8d5aSRushil Gupta int page_id = index >> (PAGE_SHIFT - GVE_TX_BUF_SHIFT_DQO);
651a6fb8d5aSRushil Gupta int offset = (index & (GVE_TX_BUFS_PER_PAGE_DQO - 1)) << GVE_TX_BUF_SHIFT_DQO;
652a6fb8d5aSRushil Gupta
653a6fb8d5aSRushil Gupta *va = page_address(tx->dqo.qpl->pages[page_id]) + offset;
654a6fb8d5aSRushil Gupta *dma_addr = tx->dqo.qpl->page_buses[page_id] + offset;
655a6fb8d5aSRushil Gupta }
656a6fb8d5aSRushil Gupta
gve_tx_add_skb_copy_dqo(struct gve_tx_ring * tx,struct sk_buff * skb,struct gve_tx_pending_packet_dqo * pkt,s16 completion_tag,u32 * desc_idx,bool is_gso)657a6fb8d5aSRushil Gupta static int gve_tx_add_skb_copy_dqo(struct gve_tx_ring *tx,
658a6fb8d5aSRushil Gupta struct sk_buff *skb,
659a6fb8d5aSRushil Gupta struct gve_tx_pending_packet_dqo *pkt,
660a6fb8d5aSRushil Gupta s16 completion_tag,
661a6fb8d5aSRushil Gupta u32 *desc_idx,
662a6fb8d5aSRushil Gupta bool is_gso)
663a6fb8d5aSRushil Gupta {
664a6fb8d5aSRushil Gupta u32 copy_offset = 0;
665a6fb8d5aSRushil Gupta dma_addr_t dma_addr;
666a6fb8d5aSRushil Gupta u32 copy_len;
667a6fb8d5aSRushil Gupta s16 index;
668a6fb8d5aSRushil Gupta void *va;
669a6fb8d5aSRushil Gupta
670a6fb8d5aSRushil Gupta /* Break the packet into buffer size chunks */
671a6fb8d5aSRushil Gupta pkt->num_bufs = 0;
672a6fb8d5aSRushil Gupta while (copy_offset < skb->len) {
673a6fb8d5aSRushil Gupta index = gve_alloc_tx_qpl_buf(tx);
674a6fb8d5aSRushil Gupta if (unlikely(index == -1))
675a6fb8d5aSRushil Gupta goto err;
676a6fb8d5aSRushil Gupta
677a6fb8d5aSRushil Gupta gve_tx_buf_get_addr(tx, index, &va, &dma_addr);
678a6fb8d5aSRushil Gupta copy_len = min_t(u32, GVE_TX_BUF_SIZE_DQO,
679a6fb8d5aSRushil Gupta skb->len - copy_offset);
680a6fb8d5aSRushil Gupta skb_copy_bits(skb, copy_offset, va, copy_len);
681a6fb8d5aSRushil Gupta
682a6fb8d5aSRushil Gupta copy_offset += copy_len;
683a6fb8d5aSRushil Gupta dma_sync_single_for_device(tx->dev, dma_addr,
684a6fb8d5aSRushil Gupta copy_len, DMA_TO_DEVICE);
685a6fb8d5aSRushil Gupta gve_tx_fill_pkt_desc_dqo(tx, desc_idx, skb,
686a6fb8d5aSRushil Gupta copy_len,
687a6fb8d5aSRushil Gupta dma_addr,
688a6fb8d5aSRushil Gupta completion_tag,
689a6fb8d5aSRushil Gupta copy_offset == skb->len,
690a6fb8d5aSRushil Gupta is_gso);
691a6fb8d5aSRushil Gupta
692a6fb8d5aSRushil Gupta pkt->tx_qpl_buf_ids[pkt->num_bufs] = index;
693a6fb8d5aSRushil Gupta ++tx->dqo_tx.alloc_tx_qpl_buf_cnt;
694a6fb8d5aSRushil Gupta ++pkt->num_bufs;
695a6fb8d5aSRushil Gupta }
696a6fb8d5aSRushil Gupta
697a6fb8d5aSRushil Gupta return 0;
698a6fb8d5aSRushil Gupta err:
699a6fb8d5aSRushil Gupta /* Should not be here if gve_has_free_tx_qpl_bufs() check is correct */
700a6fb8d5aSRushil Gupta gve_free_tx_qpl_bufs(tx, pkt);
701a6fb8d5aSRushil Gupta return -ENOMEM;
702a6fb8d5aSRushil Gupta }
703a6fb8d5aSRushil Gupta
704a6fb8d5aSRushil Gupta /* Returns 0 on success, or < 0 on error.
705a6fb8d5aSRushil Gupta *
706a6fb8d5aSRushil Gupta * Before this function is called, the caller must ensure
707a6fb8d5aSRushil Gupta * gve_has_pending_packet(tx) returns true.
708a6fb8d5aSRushil Gupta */
gve_tx_add_skb_dqo(struct gve_tx_ring * tx,struct sk_buff * skb)709a6fb8d5aSRushil Gupta static int gve_tx_add_skb_dqo(struct gve_tx_ring *tx,
710a6fb8d5aSRushil Gupta struct sk_buff *skb)
711a6fb8d5aSRushil Gupta {
712a6fb8d5aSRushil Gupta const bool is_gso = skb_is_gso(skb);
713a6fb8d5aSRushil Gupta u32 desc_idx = tx->dqo_tx.tail;
714a6fb8d5aSRushil Gupta struct gve_tx_pending_packet_dqo *pkt;
715a6fb8d5aSRushil Gupta struct gve_tx_metadata_dqo metadata;
716a6fb8d5aSRushil Gupta s16 completion_tag;
717a6fb8d5aSRushil Gupta
718a6fb8d5aSRushil Gupta pkt = gve_alloc_pending_packet(tx);
719a6fb8d5aSRushil Gupta pkt->skb = skb;
720a6fb8d5aSRushil Gupta completion_tag = pkt - tx->dqo.pending_packets;
721a6fb8d5aSRushil Gupta
722a6fb8d5aSRushil Gupta gve_extract_tx_metadata_dqo(skb, &metadata);
723a6fb8d5aSRushil Gupta if (is_gso) {
724a6fb8d5aSRushil Gupta int header_len = gve_prep_tso(skb);
725a6fb8d5aSRushil Gupta
726a6fb8d5aSRushil Gupta if (unlikely(header_len < 0))
727a6fb8d5aSRushil Gupta goto err;
728a6fb8d5aSRushil Gupta
729a6fb8d5aSRushil Gupta gve_tx_fill_tso_ctx_desc(&tx->dqo.tx_ring[desc_idx].tso_ctx,
730a6fb8d5aSRushil Gupta skb, &metadata, header_len);
731a6fb8d5aSRushil Gupta desc_idx = (desc_idx + 1) & tx->mask;
732a6fb8d5aSRushil Gupta }
733a6fb8d5aSRushil Gupta
734a6fb8d5aSRushil Gupta gve_tx_fill_general_ctx_desc(&tx->dqo.tx_ring[desc_idx].general_ctx,
735a6fb8d5aSRushil Gupta &metadata);
736a6fb8d5aSRushil Gupta desc_idx = (desc_idx + 1) & tx->mask;
737a6fb8d5aSRushil Gupta
738a6fb8d5aSRushil Gupta if (tx->dqo.qpl) {
739a6fb8d5aSRushil Gupta if (gve_tx_add_skb_copy_dqo(tx, skb, pkt,
740a6fb8d5aSRushil Gupta completion_tag,
741a6fb8d5aSRushil Gupta &desc_idx, is_gso))
742a6fb8d5aSRushil Gupta goto err;
743a6fb8d5aSRushil Gupta } else {
744a6fb8d5aSRushil Gupta if (gve_tx_add_skb_no_copy_dqo(tx, skb, pkt,
745a6fb8d5aSRushil Gupta completion_tag,
746a6fb8d5aSRushil Gupta &desc_idx, is_gso))
747a6fb8d5aSRushil Gupta goto err;
748a6fb8d5aSRushil Gupta }
749a6fb8d5aSRushil Gupta
750a6fb8d5aSRushil Gupta tx->dqo_tx.posted_packet_desc_cnt += pkt->num_bufs;
751a6fb8d5aSRushil Gupta
752a57e5de4SBailey Forrest /* Commit the changes to our state */
753a57e5de4SBailey Forrest tx->dqo_tx.tail = desc_idx;
754a57e5de4SBailey Forrest
755a57e5de4SBailey Forrest /* Request a descriptor completion on the last descriptor of the
756a57e5de4SBailey Forrest * packet if we are allowed to by the HW enforced interval.
757a57e5de4SBailey Forrest */
758a57e5de4SBailey Forrest {
759a57e5de4SBailey Forrest u32 last_desc_idx = (desc_idx - 1) & tx->mask;
760a57e5de4SBailey Forrest u32 last_report_event_interval =
761a57e5de4SBailey Forrest (last_desc_idx - tx->dqo_tx.last_re_idx) & tx->mask;
762a57e5de4SBailey Forrest
763a57e5de4SBailey Forrest if (unlikely(last_report_event_interval >=
764a57e5de4SBailey Forrest GVE_TX_MIN_RE_INTERVAL)) {
765a57e5de4SBailey Forrest tx->dqo.tx_ring[last_desc_idx].pkt.report_event = true;
766a57e5de4SBailey Forrest tx->dqo_tx.last_re_idx = last_desc_idx;
767a57e5de4SBailey Forrest }
768a57e5de4SBailey Forrest }
769a57e5de4SBailey Forrest
770a57e5de4SBailey Forrest return 0;
771a57e5de4SBailey Forrest
772a57e5de4SBailey Forrest err:
7731e0083bdSArnd Bergmann pkt->skb = NULL;
7741e0083bdSArnd Bergmann gve_free_pending_packet(tx, pkt);
775a57e5de4SBailey Forrest
776a57e5de4SBailey Forrest return -1;
777a57e5de4SBailey Forrest }
778a57e5de4SBailey Forrest
gve_num_descs_per_buf(size_t size)779a57e5de4SBailey Forrest static int gve_num_descs_per_buf(size_t size)
780a57e5de4SBailey Forrest {
781a57e5de4SBailey Forrest return DIV_ROUND_UP(size, GVE_TX_MAX_BUF_SIZE_DQO);
782a57e5de4SBailey Forrest }
783a57e5de4SBailey Forrest
gve_num_buffer_descs_needed(const struct sk_buff * skb)784a57e5de4SBailey Forrest static int gve_num_buffer_descs_needed(const struct sk_buff *skb)
785a57e5de4SBailey Forrest {
786a57e5de4SBailey Forrest const struct skb_shared_info *shinfo = skb_shinfo(skb);
787a57e5de4SBailey Forrest int num_descs;
788a57e5de4SBailey Forrest int i;
789a57e5de4SBailey Forrest
790a57e5de4SBailey Forrest num_descs = gve_num_descs_per_buf(skb_headlen(skb));
791a57e5de4SBailey Forrest
792a57e5de4SBailey Forrest for (i = 0; i < shinfo->nr_frags; i++) {
793a57e5de4SBailey Forrest unsigned int frag_size = skb_frag_size(&shinfo->frags[i]);
794a57e5de4SBailey Forrest
795a57e5de4SBailey Forrest num_descs += gve_num_descs_per_buf(frag_size);
796a57e5de4SBailey Forrest }
797a57e5de4SBailey Forrest
798a57e5de4SBailey Forrest return num_descs;
799a57e5de4SBailey Forrest }
800a57e5de4SBailey Forrest
801a57e5de4SBailey Forrest /* Returns true if HW is capable of sending TSO represented by `skb`.
802a57e5de4SBailey Forrest *
803a57e5de4SBailey Forrest * Each segment must not span more than GVE_TX_MAX_DATA_DESCS buffers.
804a57e5de4SBailey Forrest * - The header is counted as one buffer for every single segment.
805a57e5de4SBailey Forrest * - A buffer which is split between two segments is counted for both.
806a57e5de4SBailey Forrest * - If a buffer contains both header and payload, it is counted as two buffers.
807a57e5de4SBailey Forrest */
gve_can_send_tso(const struct sk_buff * skb)808a57e5de4SBailey Forrest static bool gve_can_send_tso(const struct sk_buff *skb)
809a57e5de4SBailey Forrest {
810a57e5de4SBailey Forrest const int max_bufs_per_seg = GVE_TX_MAX_DATA_DESCS - 1;
811a57e5de4SBailey Forrest const struct skb_shared_info *shinfo = skb_shinfo(skb);
812504148feSEric Dumazet const int header_len = skb_tcp_all_headers(skb);
813a57e5de4SBailey Forrest const int gso_size = shinfo->gso_size;
814a57e5de4SBailey Forrest int cur_seg_num_bufs;
815*d7725032SBailey Forrest int prev_frag_size;
816a57e5de4SBailey Forrest int cur_seg_size;
817a57e5de4SBailey Forrest int i;
818a57e5de4SBailey Forrest
819a57e5de4SBailey Forrest cur_seg_size = skb_headlen(skb) - header_len;
820*d7725032SBailey Forrest prev_frag_size = skb_headlen(skb);
821a57e5de4SBailey Forrest cur_seg_num_bufs = cur_seg_size > 0;
822a57e5de4SBailey Forrest
823a57e5de4SBailey Forrest for (i = 0; i < shinfo->nr_frags; i++) {
824a57e5de4SBailey Forrest if (cur_seg_size >= gso_size) {
825a57e5de4SBailey Forrest cur_seg_size %= gso_size;
826a57e5de4SBailey Forrest cur_seg_num_bufs = cur_seg_size > 0;
827*d7725032SBailey Forrest
828*d7725032SBailey Forrest if (prev_frag_size > GVE_TX_MAX_BUF_SIZE_DQO) {
829*d7725032SBailey Forrest int prev_frag_remain = prev_frag_size %
830*d7725032SBailey Forrest GVE_TX_MAX_BUF_SIZE_DQO;
831*d7725032SBailey Forrest
832*d7725032SBailey Forrest /* If the last descriptor of the previous frag
833*d7725032SBailey Forrest * is less than cur_seg_size, the segment will
834*d7725032SBailey Forrest * span two descriptors in the previous frag.
835*d7725032SBailey Forrest * Since max gso size (9728) is less than
836*d7725032SBailey Forrest * GVE_TX_MAX_BUF_SIZE_DQO, it is impossible
837*d7725032SBailey Forrest * for the segment to span more than two
838*d7725032SBailey Forrest * descriptors.
839*d7725032SBailey Forrest */
840*d7725032SBailey Forrest if (prev_frag_remain &&
841*d7725032SBailey Forrest cur_seg_size > prev_frag_remain)
842*d7725032SBailey Forrest cur_seg_num_bufs++;
843*d7725032SBailey Forrest }
844a57e5de4SBailey Forrest }
845a57e5de4SBailey Forrest
846a57e5de4SBailey Forrest if (unlikely(++cur_seg_num_bufs > max_bufs_per_seg))
847a57e5de4SBailey Forrest return false;
848a57e5de4SBailey Forrest
849*d7725032SBailey Forrest prev_frag_size = skb_frag_size(&shinfo->frags[i]);
850*d7725032SBailey Forrest cur_seg_size += prev_frag_size;
851a57e5de4SBailey Forrest }
852a57e5de4SBailey Forrest
853a57e5de4SBailey Forrest return true;
854a57e5de4SBailey Forrest }
855a57e5de4SBailey Forrest
856a57e5de4SBailey Forrest /* Attempt to transmit specified SKB.
857a57e5de4SBailey Forrest *
858a57e5de4SBailey Forrest * Returns 0 if the SKB was transmitted or dropped.
859a57e5de4SBailey Forrest * Returns -1 if there is not currently enough space to transmit the SKB.
860a57e5de4SBailey Forrest */
gve_try_tx_skb(struct gve_priv * priv,struct gve_tx_ring * tx,struct sk_buff * skb)861a57e5de4SBailey Forrest static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx,
862a57e5de4SBailey Forrest struct sk_buff *skb)
863a57e5de4SBailey Forrest {
864a57e5de4SBailey Forrest int num_buffer_descs;
865a57e5de4SBailey Forrest int total_num_descs;
866a57e5de4SBailey Forrest
867a6fb8d5aSRushil Gupta if (tx->dqo.qpl) {
868a6fb8d5aSRushil Gupta if (skb_is_gso(skb))
869a6fb8d5aSRushil Gupta if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
870a6fb8d5aSRushil Gupta goto drop;
871a6fb8d5aSRushil Gupta
872a6fb8d5aSRushil Gupta /* We do not need to verify the number of buffers used per
873a6fb8d5aSRushil Gupta * packet or per segment in case of TSO as with 2K size buffers
874a6fb8d5aSRushil Gupta * none of the TX packet rules would be violated.
875a6fb8d5aSRushil Gupta *
876a6fb8d5aSRushil Gupta * gve_can_send_tso() checks that each TCP segment of gso_size is
877a6fb8d5aSRushil Gupta * not distributed over more than 9 SKB frags..
878a6fb8d5aSRushil Gupta */
879a6fb8d5aSRushil Gupta num_buffer_descs = DIV_ROUND_UP(skb->len, GVE_TX_BUF_SIZE_DQO);
880a6fb8d5aSRushil Gupta } else {
881a57e5de4SBailey Forrest if (skb_is_gso(skb)) {
882a57e5de4SBailey Forrest /* If TSO doesn't meet HW requirements, attempt to linearize the
883a57e5de4SBailey Forrest * packet.
884a57e5de4SBailey Forrest */
885a57e5de4SBailey Forrest if (unlikely(!gve_can_send_tso(skb) &&
886a57e5de4SBailey Forrest skb_linearize(skb) < 0)) {
887a57e5de4SBailey Forrest net_err_ratelimited("%s: Failed to transmit TSO packet\n",
888a57e5de4SBailey Forrest priv->dev->name);
889a57e5de4SBailey Forrest goto drop;
890a57e5de4SBailey Forrest }
891a57e5de4SBailey Forrest
892a695641cSCoco Li if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
893a695641cSCoco Li goto drop;
894a695641cSCoco Li
895a57e5de4SBailey Forrest num_buffer_descs = gve_num_buffer_descs_needed(skb);
896a57e5de4SBailey Forrest } else {
897a57e5de4SBailey Forrest num_buffer_descs = gve_num_buffer_descs_needed(skb);
898a57e5de4SBailey Forrest
899a57e5de4SBailey Forrest if (unlikely(num_buffer_descs > GVE_TX_MAX_DATA_DESCS)) {
900a57e5de4SBailey Forrest if (unlikely(skb_linearize(skb) < 0))
901a57e5de4SBailey Forrest goto drop;
902a57e5de4SBailey Forrest
903a57e5de4SBailey Forrest num_buffer_descs = 1;
904a57e5de4SBailey Forrest }
905a57e5de4SBailey Forrest }
906a6fb8d5aSRushil Gupta }
907a57e5de4SBailey Forrest
908a57e5de4SBailey Forrest /* Metadata + (optional TSO) + data descriptors. */
909a57e5de4SBailey Forrest total_num_descs = 1 + skb_is_gso(skb) + num_buffer_descs;
910a57e5de4SBailey Forrest if (unlikely(gve_maybe_stop_tx_dqo(tx, total_num_descs +
911a6fb8d5aSRushil Gupta GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP,
912a6fb8d5aSRushil Gupta num_buffer_descs))) {
913a57e5de4SBailey Forrest return -1;
914a57e5de4SBailey Forrest }
915a57e5de4SBailey Forrest
916a6fb8d5aSRushil Gupta if (unlikely(gve_tx_add_skb_dqo(tx, skb) < 0))
917a57e5de4SBailey Forrest goto drop;
918a57e5de4SBailey Forrest
919a57e5de4SBailey Forrest netdev_tx_sent_queue(tx->netdev_txq, skb->len);
920a57e5de4SBailey Forrest skb_tx_timestamp(skb);
921a57e5de4SBailey Forrest return 0;
922a57e5de4SBailey Forrest
923a57e5de4SBailey Forrest drop:
924a57e5de4SBailey Forrest tx->dropped_pkt++;
925a57e5de4SBailey Forrest dev_kfree_skb_any(skb);
926a57e5de4SBailey Forrest return 0;
927a57e5de4SBailey Forrest }
928a57e5de4SBailey Forrest
929a57e5de4SBailey Forrest /* Transmit a given skb and ring the doorbell. */
gve_tx_dqo(struct sk_buff * skb,struct net_device * dev)9305e8c5adfSBailey Forrest netdev_tx_t gve_tx_dqo(struct sk_buff *skb, struct net_device *dev)
9315e8c5adfSBailey Forrest {
932a57e5de4SBailey Forrest struct gve_priv *priv = netdev_priv(dev);
933a57e5de4SBailey Forrest struct gve_tx_ring *tx;
934a57e5de4SBailey Forrest
935a57e5de4SBailey Forrest tx = &priv->tx[skb_get_queue_mapping(skb)];
936a57e5de4SBailey Forrest if (unlikely(gve_try_tx_skb(priv, tx, skb) < 0)) {
937a57e5de4SBailey Forrest /* We need to ring the txq doorbell -- we have stopped the Tx
938a57e5de4SBailey Forrest * queue for want of resources, but prior calls to gve_tx()
939a57e5de4SBailey Forrest * may have added descriptors without ringing the doorbell.
940a57e5de4SBailey Forrest */
941a57e5de4SBailey Forrest gve_tx_put_doorbell_dqo(priv, tx->q_resources, tx->dqo_tx.tail);
942a57e5de4SBailey Forrest return NETDEV_TX_BUSY;
943a57e5de4SBailey Forrest }
944a57e5de4SBailey Forrest
945a57e5de4SBailey Forrest if (!netif_xmit_stopped(tx->netdev_txq) && netdev_xmit_more())
9465e8c5adfSBailey Forrest return NETDEV_TX_OK;
947a57e5de4SBailey Forrest
948a57e5de4SBailey Forrest gve_tx_put_doorbell_dqo(priv, tx->q_resources, tx->dqo_tx.tail);
949a57e5de4SBailey Forrest return NETDEV_TX_OK;
950a57e5de4SBailey Forrest }
951a57e5de4SBailey Forrest
add_to_list(struct gve_tx_ring * tx,struct gve_index_list * list,struct gve_tx_pending_packet_dqo * pending_packet)952a57e5de4SBailey Forrest static void add_to_list(struct gve_tx_ring *tx, struct gve_index_list *list,
953a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet)
954a57e5de4SBailey Forrest {
955a57e5de4SBailey Forrest s16 old_tail, index;
956a57e5de4SBailey Forrest
957a57e5de4SBailey Forrest index = pending_packet - tx->dqo.pending_packets;
958a57e5de4SBailey Forrest old_tail = list->tail;
959a57e5de4SBailey Forrest list->tail = index;
960a57e5de4SBailey Forrest if (old_tail == -1)
961a57e5de4SBailey Forrest list->head = index;
962a57e5de4SBailey Forrest else
963a57e5de4SBailey Forrest tx->dqo.pending_packets[old_tail].next = index;
964a57e5de4SBailey Forrest
965a57e5de4SBailey Forrest pending_packet->next = -1;
966a57e5de4SBailey Forrest pending_packet->prev = old_tail;
967a57e5de4SBailey Forrest }
968a57e5de4SBailey Forrest
remove_from_list(struct gve_tx_ring * tx,struct gve_index_list * list,struct gve_tx_pending_packet_dqo * pkt)969a57e5de4SBailey Forrest static void remove_from_list(struct gve_tx_ring *tx,
970a57e5de4SBailey Forrest struct gve_index_list *list,
9711e0083bdSArnd Bergmann struct gve_tx_pending_packet_dqo *pkt)
972a57e5de4SBailey Forrest {
973e8192476SBailey Forrest s16 prev_index, next_index;
974a57e5de4SBailey Forrest
9751e0083bdSArnd Bergmann prev_index = pkt->prev;
9761e0083bdSArnd Bergmann next_index = pkt->next;
977a57e5de4SBailey Forrest
978a57e5de4SBailey Forrest if (prev_index == -1) {
979a57e5de4SBailey Forrest /* Node is head */
980a57e5de4SBailey Forrest list->head = next_index;
981a57e5de4SBailey Forrest } else {
982a57e5de4SBailey Forrest tx->dqo.pending_packets[prev_index].next = next_index;
983a57e5de4SBailey Forrest }
984a57e5de4SBailey Forrest if (next_index == -1) {
985a57e5de4SBailey Forrest /* Node is tail */
986a57e5de4SBailey Forrest list->tail = prev_index;
987a57e5de4SBailey Forrest } else {
988a57e5de4SBailey Forrest tx->dqo.pending_packets[next_index].prev = prev_index;
989a57e5de4SBailey Forrest }
990a57e5de4SBailey Forrest }
991a57e5de4SBailey Forrest
gve_unmap_packet(struct device * dev,struct gve_tx_pending_packet_dqo * pkt)992a57e5de4SBailey Forrest static void gve_unmap_packet(struct device *dev,
9931e0083bdSArnd Bergmann struct gve_tx_pending_packet_dqo *pkt)
994a57e5de4SBailey Forrest {
995a57e5de4SBailey Forrest int i;
996a57e5de4SBailey Forrest
997a57e5de4SBailey Forrest /* SKB linear portion is guaranteed to be mapped */
9981e0083bdSArnd Bergmann dma_unmap_single(dev, dma_unmap_addr(pkt, dma[0]),
9991e0083bdSArnd Bergmann dma_unmap_len(pkt, len[0]), DMA_TO_DEVICE);
10001e0083bdSArnd Bergmann for (i = 1; i < pkt->num_bufs; i++) {
10011e0083bdSArnd Bergmann dma_unmap_page(dev, dma_unmap_addr(pkt, dma[i]),
10021e0083bdSArnd Bergmann dma_unmap_len(pkt, len[i]), DMA_TO_DEVICE);
1003a57e5de4SBailey Forrest }
10041e0083bdSArnd Bergmann pkt->num_bufs = 0;
1005a57e5de4SBailey Forrest }
1006a57e5de4SBailey Forrest
1007a57e5de4SBailey Forrest /* Completion types and expected behavior:
1008a57e5de4SBailey Forrest * No Miss compl + Packet compl = Packet completed normally.
1009a57e5de4SBailey Forrest * Miss compl + Re-inject compl = Packet completed normally.
1010a57e5de4SBailey Forrest * No Miss compl + Re-inject compl = Skipped i.e. packet not completed.
1011a57e5de4SBailey Forrest * Miss compl + Packet compl = Skipped i.e. packet not completed.
1012a57e5de4SBailey Forrest */
gve_handle_packet_completion(struct gve_priv * priv,struct gve_tx_ring * tx,bool is_napi,u16 compl_tag,u64 * bytes,u64 * pkts,bool is_reinjection)1013a57e5de4SBailey Forrest static void gve_handle_packet_completion(struct gve_priv *priv,
1014a57e5de4SBailey Forrest struct gve_tx_ring *tx, bool is_napi,
1015a57e5de4SBailey Forrest u16 compl_tag, u64 *bytes, u64 *pkts,
1016a57e5de4SBailey Forrest bool is_reinjection)
1017a57e5de4SBailey Forrest {
1018a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet;
1019a57e5de4SBailey Forrest
1020a57e5de4SBailey Forrest if (unlikely(compl_tag >= tx->dqo.num_pending_packets)) {
1021a57e5de4SBailey Forrest net_err_ratelimited("%s: Invalid TX completion tag: %d\n",
1022a57e5de4SBailey Forrest priv->dev->name, (int)compl_tag);
1023a57e5de4SBailey Forrest return;
1024a57e5de4SBailey Forrest }
1025a57e5de4SBailey Forrest
1026a57e5de4SBailey Forrest pending_packet = &tx->dqo.pending_packets[compl_tag];
1027a57e5de4SBailey Forrest
1028a57e5de4SBailey Forrest if (unlikely(is_reinjection)) {
1029a57e5de4SBailey Forrest if (unlikely(pending_packet->state ==
1030a57e5de4SBailey Forrest GVE_PACKET_STATE_TIMED_OUT_COMPL)) {
1031a57e5de4SBailey Forrest net_err_ratelimited("%s: Re-injection completion: %d received after timeout.\n",
1032a57e5de4SBailey Forrest priv->dev->name, (int)compl_tag);
1033a57e5de4SBailey Forrest /* Packet was already completed as a result of timeout,
1034a57e5de4SBailey Forrest * so just remove from list and free pending packet.
1035a57e5de4SBailey Forrest */
1036a57e5de4SBailey Forrest remove_from_list(tx,
1037a57e5de4SBailey Forrest &tx->dqo_compl.timed_out_completions,
1038a57e5de4SBailey Forrest pending_packet);
1039a57e5de4SBailey Forrest gve_free_pending_packet(tx, pending_packet);
1040a57e5de4SBailey Forrest return;
1041a57e5de4SBailey Forrest }
1042a57e5de4SBailey Forrest if (unlikely(pending_packet->state !=
1043a57e5de4SBailey Forrest GVE_PACKET_STATE_PENDING_REINJECT_COMPL)) {
1044a57e5de4SBailey Forrest /* No outstanding miss completion but packet allocated
1045a57e5de4SBailey Forrest * implies packet receives a re-injection completion
1046577d7685SJilin Yuan * without a prior miss completion. Return without
1047a57e5de4SBailey Forrest * completing the packet.
1048a57e5de4SBailey Forrest */
1049a57e5de4SBailey Forrest net_err_ratelimited("%s: Re-injection completion received without corresponding miss completion: %d\n",
1050a57e5de4SBailey Forrest priv->dev->name, (int)compl_tag);
1051a57e5de4SBailey Forrest return;
1052a57e5de4SBailey Forrest }
1053a57e5de4SBailey Forrest remove_from_list(tx, &tx->dqo_compl.miss_completions,
1054a57e5de4SBailey Forrest pending_packet);
1055a57e5de4SBailey Forrest } else {
1056a57e5de4SBailey Forrest /* Packet is allocated but not a pending data completion. */
1057a57e5de4SBailey Forrest if (unlikely(pending_packet->state !=
1058a57e5de4SBailey Forrest GVE_PACKET_STATE_PENDING_DATA_COMPL)) {
1059a57e5de4SBailey Forrest net_err_ratelimited("%s: No pending data completion: %d\n",
1060a57e5de4SBailey Forrest priv->dev->name, (int)compl_tag);
1061a57e5de4SBailey Forrest return;
1062a57e5de4SBailey Forrest }
1063a57e5de4SBailey Forrest }
1064a6fb8d5aSRushil Gupta tx->dqo_tx.completed_packet_desc_cnt += pending_packet->num_bufs;
1065a6fb8d5aSRushil Gupta if (tx->dqo.qpl)
1066a6fb8d5aSRushil Gupta gve_free_tx_qpl_bufs(tx, pending_packet);
1067a6fb8d5aSRushil Gupta else
1068a57e5de4SBailey Forrest gve_unmap_packet(tx->dev, pending_packet);
1069a57e5de4SBailey Forrest
1070a57e5de4SBailey Forrest *bytes += pending_packet->skb->len;
1071a57e5de4SBailey Forrest (*pkts)++;
1072a57e5de4SBailey Forrest napi_consume_skb(pending_packet->skb, is_napi);
1073a57e5de4SBailey Forrest pending_packet->skb = NULL;
1074a57e5de4SBailey Forrest gve_free_pending_packet(tx, pending_packet);
1075a57e5de4SBailey Forrest }
1076a57e5de4SBailey Forrest
gve_handle_miss_completion(struct gve_priv * priv,struct gve_tx_ring * tx,u16 compl_tag,u64 * bytes,u64 * pkts)1077a57e5de4SBailey Forrest static void gve_handle_miss_completion(struct gve_priv *priv,
1078a57e5de4SBailey Forrest struct gve_tx_ring *tx, u16 compl_tag,
1079a57e5de4SBailey Forrest u64 *bytes, u64 *pkts)
1080a57e5de4SBailey Forrest {
1081a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet;
1082a57e5de4SBailey Forrest
1083a57e5de4SBailey Forrest if (unlikely(compl_tag >= tx->dqo.num_pending_packets)) {
1084a57e5de4SBailey Forrest net_err_ratelimited("%s: Invalid TX completion tag: %d\n",
1085a57e5de4SBailey Forrest priv->dev->name, (int)compl_tag);
1086a57e5de4SBailey Forrest return;
1087a57e5de4SBailey Forrest }
1088a57e5de4SBailey Forrest
1089a57e5de4SBailey Forrest pending_packet = &tx->dqo.pending_packets[compl_tag];
1090a57e5de4SBailey Forrest if (unlikely(pending_packet->state !=
1091a57e5de4SBailey Forrest GVE_PACKET_STATE_PENDING_DATA_COMPL)) {
1092a57e5de4SBailey Forrest net_err_ratelimited("%s: Unexpected packet state: %d for completion tag : %d\n",
1093a57e5de4SBailey Forrest priv->dev->name, (int)pending_packet->state,
1094a57e5de4SBailey Forrest (int)compl_tag);
1095a57e5de4SBailey Forrest return;
1096a57e5de4SBailey Forrest }
1097a57e5de4SBailey Forrest
1098a57e5de4SBailey Forrest pending_packet->state = GVE_PACKET_STATE_PENDING_REINJECT_COMPL;
1099a57e5de4SBailey Forrest /* jiffies can wraparound but time comparisons can handle overflows. */
1100a57e5de4SBailey Forrest pending_packet->timeout_jiffies =
1101a57e5de4SBailey Forrest jiffies +
1102a57e5de4SBailey Forrest msecs_to_jiffies(GVE_REINJECT_COMPL_TIMEOUT *
1103a57e5de4SBailey Forrest MSEC_PER_SEC);
1104a57e5de4SBailey Forrest add_to_list(tx, &tx->dqo_compl.miss_completions, pending_packet);
1105a57e5de4SBailey Forrest
1106a57e5de4SBailey Forrest *bytes += pending_packet->skb->len;
1107a57e5de4SBailey Forrest (*pkts)++;
1108a57e5de4SBailey Forrest }
1109a57e5de4SBailey Forrest
remove_miss_completions(struct gve_priv * priv,struct gve_tx_ring * tx)1110a57e5de4SBailey Forrest static void remove_miss_completions(struct gve_priv *priv,
1111a57e5de4SBailey Forrest struct gve_tx_ring *tx)
1112a57e5de4SBailey Forrest {
1113a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet;
1114a57e5de4SBailey Forrest s16 next_index;
1115a57e5de4SBailey Forrest
1116a57e5de4SBailey Forrest next_index = tx->dqo_compl.miss_completions.head;
1117a57e5de4SBailey Forrest while (next_index != -1) {
1118a57e5de4SBailey Forrest pending_packet = &tx->dqo.pending_packets[next_index];
1119a57e5de4SBailey Forrest next_index = pending_packet->next;
1120a57e5de4SBailey Forrest /* Break early because packets should timeout in order. */
1121a57e5de4SBailey Forrest if (time_is_after_jiffies(pending_packet->timeout_jiffies))
1122a57e5de4SBailey Forrest break;
1123a57e5de4SBailey Forrest
1124a57e5de4SBailey Forrest remove_from_list(tx, &tx->dqo_compl.miss_completions,
1125a57e5de4SBailey Forrest pending_packet);
1126a6fb8d5aSRushil Gupta /* Unmap/free TX buffers and free skb but do not unallocate packet i.e.
1127a57e5de4SBailey Forrest * the completion tag is not freed to ensure that the driver
1128a57e5de4SBailey Forrest * can take appropriate action if a corresponding valid
1129a57e5de4SBailey Forrest * completion is received later.
1130a57e5de4SBailey Forrest */
1131a6fb8d5aSRushil Gupta if (tx->dqo.qpl)
1132a6fb8d5aSRushil Gupta gve_free_tx_qpl_bufs(tx, pending_packet);
1133a6fb8d5aSRushil Gupta else
1134a57e5de4SBailey Forrest gve_unmap_packet(tx->dev, pending_packet);
1135a6fb8d5aSRushil Gupta
1136a57e5de4SBailey Forrest /* This indicates the packet was dropped. */
1137a57e5de4SBailey Forrest dev_kfree_skb_any(pending_packet->skb);
1138a57e5de4SBailey Forrest pending_packet->skb = NULL;
1139a57e5de4SBailey Forrest tx->dropped_pkt++;
1140e8192476SBailey Forrest net_err_ratelimited("%s: No reinjection completion was received for: %d.\n",
1141a57e5de4SBailey Forrest priv->dev->name,
1142e8192476SBailey Forrest (int)(pending_packet - tx->dqo.pending_packets));
1143a57e5de4SBailey Forrest
1144a57e5de4SBailey Forrest pending_packet->state = GVE_PACKET_STATE_TIMED_OUT_COMPL;
1145a57e5de4SBailey Forrest pending_packet->timeout_jiffies =
1146a57e5de4SBailey Forrest jiffies +
1147a57e5de4SBailey Forrest msecs_to_jiffies(GVE_DEALLOCATE_COMPL_TIMEOUT *
1148a57e5de4SBailey Forrest MSEC_PER_SEC);
1149a57e5de4SBailey Forrest /* Maintain pending packet in another list so the packet can be
1150a57e5de4SBailey Forrest * unallocated at a later time.
1151a57e5de4SBailey Forrest */
1152a57e5de4SBailey Forrest add_to_list(tx, &tx->dqo_compl.timed_out_completions,
1153a57e5de4SBailey Forrest pending_packet);
1154a57e5de4SBailey Forrest }
1155a57e5de4SBailey Forrest }
1156a57e5de4SBailey Forrest
remove_timed_out_completions(struct gve_priv * priv,struct gve_tx_ring * tx)1157a57e5de4SBailey Forrest static void remove_timed_out_completions(struct gve_priv *priv,
1158a57e5de4SBailey Forrest struct gve_tx_ring *tx)
1159a57e5de4SBailey Forrest {
1160a57e5de4SBailey Forrest struct gve_tx_pending_packet_dqo *pending_packet;
1161a57e5de4SBailey Forrest s16 next_index;
1162a57e5de4SBailey Forrest
1163a57e5de4SBailey Forrest next_index = tx->dqo_compl.timed_out_completions.head;
1164a57e5de4SBailey Forrest while (next_index != -1) {
1165a57e5de4SBailey Forrest pending_packet = &tx->dqo.pending_packets[next_index];
1166a57e5de4SBailey Forrest next_index = pending_packet->next;
1167a57e5de4SBailey Forrest /* Break early because packets should timeout in order. */
1168a57e5de4SBailey Forrest if (time_is_after_jiffies(pending_packet->timeout_jiffies))
1169a57e5de4SBailey Forrest break;
1170a57e5de4SBailey Forrest
1171a57e5de4SBailey Forrest remove_from_list(tx, &tx->dqo_compl.timed_out_completions,
1172a57e5de4SBailey Forrest pending_packet);
1173a57e5de4SBailey Forrest gve_free_pending_packet(tx, pending_packet);
1174a57e5de4SBailey Forrest }
11755e8c5adfSBailey Forrest }
11765e8c5adfSBailey Forrest
gve_clean_tx_done_dqo(struct gve_priv * priv,struct gve_tx_ring * tx,struct napi_struct * napi)11779c1a59a2SBailey Forrest int gve_clean_tx_done_dqo(struct gve_priv *priv, struct gve_tx_ring *tx,
11789c1a59a2SBailey Forrest struct napi_struct *napi)
11799c1a59a2SBailey Forrest {
1180a57e5de4SBailey Forrest u64 reinject_compl_bytes = 0;
1181a57e5de4SBailey Forrest u64 reinject_compl_pkts = 0;
1182a57e5de4SBailey Forrest int num_descs_cleaned = 0;
1183a57e5de4SBailey Forrest u64 miss_compl_bytes = 0;
1184a57e5de4SBailey Forrest u64 miss_compl_pkts = 0;
1185a57e5de4SBailey Forrest u64 pkt_compl_bytes = 0;
1186a57e5de4SBailey Forrest u64 pkt_compl_pkts = 0;
1187a57e5de4SBailey Forrest
1188a57e5de4SBailey Forrest /* Limit in order to avoid blocking for too long */
1189a57e5de4SBailey Forrest while (!napi || pkt_compl_pkts < napi->weight) {
1190a57e5de4SBailey Forrest struct gve_tx_compl_desc *compl_desc =
1191a57e5de4SBailey Forrest &tx->dqo.compl_ring[tx->dqo_compl.head];
1192a57e5de4SBailey Forrest u16 type;
1193a57e5de4SBailey Forrest
1194a57e5de4SBailey Forrest if (compl_desc->generation == tx->dqo_compl.cur_gen_bit)
1195a57e5de4SBailey Forrest break;
1196a57e5de4SBailey Forrest
1197a57e5de4SBailey Forrest /* Prefetch the next descriptor. */
1198a57e5de4SBailey Forrest prefetch(&tx->dqo.compl_ring[(tx->dqo_compl.head + 1) &
1199a57e5de4SBailey Forrest tx->dqo.complq_mask]);
1200a57e5de4SBailey Forrest
1201a57e5de4SBailey Forrest /* Do not read data until we own the descriptor */
1202a57e5de4SBailey Forrest dma_rmb();
1203a57e5de4SBailey Forrest type = compl_desc->type;
1204a57e5de4SBailey Forrest
1205a57e5de4SBailey Forrest if (type == GVE_COMPL_TYPE_DQO_DESC) {
1206a57e5de4SBailey Forrest /* This is the last descriptor fetched by HW plus one */
1207a57e5de4SBailey Forrest u16 tx_head = le16_to_cpu(compl_desc->tx_head);
1208a57e5de4SBailey Forrest
1209a57e5de4SBailey Forrest atomic_set_release(&tx->dqo_compl.hw_tx_head, tx_head);
1210a57e5de4SBailey Forrest } else if (type == GVE_COMPL_TYPE_DQO_PKT) {
1211a57e5de4SBailey Forrest u16 compl_tag = le16_to_cpu(compl_desc->completion_tag);
1212a5affbd8SJeroen de Borst if (compl_tag & GVE_ALT_MISS_COMPL_BIT) {
1213a5affbd8SJeroen de Borst compl_tag &= ~GVE_ALT_MISS_COMPL_BIT;
1214a5affbd8SJeroen de Borst gve_handle_miss_completion(priv, tx, compl_tag,
1215a5affbd8SJeroen de Borst &miss_compl_bytes,
1216a5affbd8SJeroen de Borst &miss_compl_pkts);
1217a5affbd8SJeroen de Borst } else {
1218a57e5de4SBailey Forrest gve_handle_packet_completion(priv, tx, !!napi,
1219a57e5de4SBailey Forrest compl_tag,
1220a57e5de4SBailey Forrest &pkt_compl_bytes,
1221a57e5de4SBailey Forrest &pkt_compl_pkts,
1222a5affbd8SJeroen de Borst false);
1223a5affbd8SJeroen de Borst }
1224a57e5de4SBailey Forrest } else if (type == GVE_COMPL_TYPE_DQO_MISS) {
1225a57e5de4SBailey Forrest u16 compl_tag = le16_to_cpu(compl_desc->completion_tag);
1226a57e5de4SBailey Forrest
1227a57e5de4SBailey Forrest gve_handle_miss_completion(priv, tx, compl_tag,
1228a57e5de4SBailey Forrest &miss_compl_bytes,
1229a57e5de4SBailey Forrest &miss_compl_pkts);
1230a57e5de4SBailey Forrest } else if (type == GVE_COMPL_TYPE_DQO_REINJECTION) {
1231a57e5de4SBailey Forrest u16 compl_tag = le16_to_cpu(compl_desc->completion_tag);
1232a57e5de4SBailey Forrest
1233a57e5de4SBailey Forrest gve_handle_packet_completion(priv, tx, !!napi,
1234a57e5de4SBailey Forrest compl_tag,
1235a57e5de4SBailey Forrest &reinject_compl_bytes,
1236a57e5de4SBailey Forrest &reinject_compl_pkts,
1237a5affbd8SJeroen de Borst true);
1238a57e5de4SBailey Forrest }
1239a57e5de4SBailey Forrest
1240a57e5de4SBailey Forrest tx->dqo_compl.head =
1241a57e5de4SBailey Forrest (tx->dqo_compl.head + 1) & tx->dqo.complq_mask;
1242a57e5de4SBailey Forrest /* Flip the generation bit when we wrap around */
1243a57e5de4SBailey Forrest tx->dqo_compl.cur_gen_bit ^= tx->dqo_compl.head == 0;
1244a57e5de4SBailey Forrest num_descs_cleaned++;
1245a57e5de4SBailey Forrest }
1246a57e5de4SBailey Forrest
1247a57e5de4SBailey Forrest netdev_tx_completed_queue(tx->netdev_txq,
1248a57e5de4SBailey Forrest pkt_compl_pkts + miss_compl_pkts,
1249a57e5de4SBailey Forrest pkt_compl_bytes + miss_compl_bytes);
1250a57e5de4SBailey Forrest
1251a57e5de4SBailey Forrest remove_miss_completions(priv, tx);
1252a57e5de4SBailey Forrest remove_timed_out_completions(priv, tx);
1253a57e5de4SBailey Forrest
1254a57e5de4SBailey Forrest u64_stats_update_begin(&tx->statss);
1255a57e5de4SBailey Forrest tx->bytes_done += pkt_compl_bytes + reinject_compl_bytes;
1256a57e5de4SBailey Forrest tx->pkt_done += pkt_compl_pkts + reinject_compl_pkts;
1257a57e5de4SBailey Forrest u64_stats_update_end(&tx->statss);
1258a57e5de4SBailey Forrest return num_descs_cleaned;
12599c1a59a2SBailey Forrest }
12609c1a59a2SBailey Forrest
gve_tx_poll_dqo(struct gve_notify_block * block,bool do_clean)12615e8c5adfSBailey Forrest bool gve_tx_poll_dqo(struct gve_notify_block *block, bool do_clean)
12625e8c5adfSBailey Forrest {
1263a57e5de4SBailey Forrest struct gve_tx_compl_desc *compl_desc;
1264a57e5de4SBailey Forrest struct gve_tx_ring *tx = block->tx;
1265a57e5de4SBailey Forrest struct gve_priv *priv = block->priv;
1266a57e5de4SBailey Forrest
1267a57e5de4SBailey Forrest if (do_clean) {
1268a57e5de4SBailey Forrest int num_descs_cleaned = gve_clean_tx_done_dqo(priv, tx,
1269a57e5de4SBailey Forrest &block->napi);
1270a57e5de4SBailey Forrest
1271a57e5de4SBailey Forrest /* Sync with queue being stopped in `gve_maybe_stop_tx_dqo()` */
1272a57e5de4SBailey Forrest mb();
1273a57e5de4SBailey Forrest
1274a57e5de4SBailey Forrest if (netif_tx_queue_stopped(tx->netdev_txq) &&
1275a57e5de4SBailey Forrest num_descs_cleaned > 0) {
1276a57e5de4SBailey Forrest tx->wake_queue++;
1277a57e5de4SBailey Forrest netif_tx_wake_queue(tx->netdev_txq);
1278a57e5de4SBailey Forrest }
1279a57e5de4SBailey Forrest }
1280a57e5de4SBailey Forrest
1281a57e5de4SBailey Forrest /* Return true if we still have work. */
1282a57e5de4SBailey Forrest compl_desc = &tx->dqo.compl_ring[tx->dqo_compl.head];
1283a57e5de4SBailey Forrest return compl_desc->generation != tx->dqo_compl.cur_gen_bit;
12845e8c5adfSBailey Forrest }
1285