145c98dacSZbigniew Bodek /*-
29eb1615fSMarcin Wojtas * SPDX-License-Identifier: BSD-3-Clause
345c98dacSZbigniew Bodek *
4adfed2d8SArthur Kiyanovski * Copyright (c) 2015-2023 Amazon.com, Inc. or its affiliates.
545c98dacSZbigniew Bodek * All rights reserved.
645c98dacSZbigniew Bodek *
745c98dacSZbigniew Bodek * Redistribution and use in source and binary forms, with or without
845c98dacSZbigniew Bodek * modification, are permitted provided that the following conditions
945c98dacSZbigniew Bodek * are met:
1045c98dacSZbigniew Bodek *
1145c98dacSZbigniew Bodek * * Redistributions of source code must retain the above copyright
1245c98dacSZbigniew Bodek * notice, this list of conditions and the following disclaimer.
1345c98dacSZbigniew Bodek * * Redistributions in binary form must reproduce the above copyright
1445c98dacSZbigniew Bodek * notice, this list of conditions and the following disclaimer in
1545c98dacSZbigniew Bodek * the documentation and/or other materials provided with the
1645c98dacSZbigniew Bodek * distribution.
1745c98dacSZbigniew Bodek * * Neither the name of copyright holder nor the names of its
1845c98dacSZbigniew Bodek * contributors may be used to endorse or promote products derived
1945c98dacSZbigniew Bodek * from this software without specific prior written permission.
2045c98dacSZbigniew Bodek *
2145c98dacSZbigniew Bodek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2245c98dacSZbigniew Bodek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2345c98dacSZbigniew Bodek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2445c98dacSZbigniew Bodek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2545c98dacSZbigniew Bodek * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2645c98dacSZbigniew Bodek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2745c98dacSZbigniew Bodek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2845c98dacSZbigniew Bodek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2945c98dacSZbigniew Bodek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3045c98dacSZbigniew Bodek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3145c98dacSZbigniew Bodek * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3245c98dacSZbigniew Bodek */
3345c98dacSZbigniew Bodek
3445c98dacSZbigniew Bodek #include "ena_eth_com.h"
3545c98dacSZbigniew Bodek
ena_com_get_next_rx_cdesc(struct ena_com_io_cq * io_cq)368483b844SMarcin Wojtas static struct ena_eth_io_rx_cdesc_base *ena_com_get_next_rx_cdesc(
3745c98dacSZbigniew Bodek struct ena_com_io_cq *io_cq)
3845c98dacSZbigniew Bodek {
3945c98dacSZbigniew Bodek struct ena_eth_io_rx_cdesc_base *cdesc;
4045c98dacSZbigniew Bodek u16 expected_phase, head_masked;
4145c98dacSZbigniew Bodek u16 desc_phase;
4245c98dacSZbigniew Bodek
4345c98dacSZbigniew Bodek head_masked = io_cq->head & (io_cq->q_depth - 1);
4445c98dacSZbigniew Bodek expected_phase = io_cq->phase;
4545c98dacSZbigniew Bodek
4645c98dacSZbigniew Bodek cdesc = (struct ena_eth_io_rx_cdesc_base *)(io_cq->cdesc_addr.virt_addr
4745c98dacSZbigniew Bodek + (head_masked * io_cq->cdesc_entry_size_in_bytes));
4845c98dacSZbigniew Bodek
4967ec48bbSMarcin Wojtas desc_phase = (READ_ONCE32(cdesc->status) & ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK) >>
5045c98dacSZbigniew Bodek ENA_ETH_IO_RX_CDESC_BASE_PHASE_SHIFT;
5145c98dacSZbigniew Bodek
5245c98dacSZbigniew Bodek if (desc_phase != expected_phase)
5345c98dacSZbigniew Bodek return NULL;
5445c98dacSZbigniew Bodek
5567ec48bbSMarcin Wojtas /* Make sure we read the rest of the descriptor after the phase bit
5667ec48bbSMarcin Wojtas * has been read
5767ec48bbSMarcin Wojtas */
5867ec48bbSMarcin Wojtas dma_rmb();
5967ec48bbSMarcin Wojtas
6045c98dacSZbigniew Bodek return cdesc;
6145c98dacSZbigniew Bodek }
6245c98dacSZbigniew Bodek
get_sq_desc_regular_queue(struct ena_com_io_sq * io_sq)638483b844SMarcin Wojtas static void *get_sq_desc_regular_queue(struct ena_com_io_sq *io_sq)
6445c98dacSZbigniew Bodek {
6545c98dacSZbigniew Bodek u16 tail_masked;
6645c98dacSZbigniew Bodek u32 offset;
6745c98dacSZbigniew Bodek
6845c98dacSZbigniew Bodek tail_masked = io_sq->tail & (io_sq->q_depth - 1);
6945c98dacSZbigniew Bodek
7045c98dacSZbigniew Bodek offset = tail_masked * io_sq->desc_entry_size;
7145c98dacSZbigniew Bodek
7245c98dacSZbigniew Bodek return (void *)((uintptr_t)io_sq->desc_addr.virt_addr + offset);
7345c98dacSZbigniew Bodek }
7445c98dacSZbigniew Bodek
ena_com_write_bounce_buffer_to_dev(struct ena_com_io_sq * io_sq,u8 * bounce_buffer)758483b844SMarcin Wojtas static int ena_com_write_bounce_buffer_to_dev(struct ena_com_io_sq *io_sq,
76a195fab0SMarcin Wojtas u8 *bounce_buffer)
7745c98dacSZbigniew Bodek {
78a195fab0SMarcin Wojtas struct ena_com_llq_info *llq_info = &io_sq->llq_info;
7945c98dacSZbigniew Bodek
80a195fab0SMarcin Wojtas u16 dst_tail_mask;
81a195fab0SMarcin Wojtas u32 dst_offset;
8245c98dacSZbigniew Bodek
83a195fab0SMarcin Wojtas dst_tail_mask = io_sq->tail & (io_sq->q_depth - 1);
84a195fab0SMarcin Wojtas dst_offset = dst_tail_mask * llq_info->desc_list_entry_size;
8545c98dacSZbigniew Bodek
8667ec48bbSMarcin Wojtas if (is_llq_max_tx_burst_exists(io_sq)) {
8767ec48bbSMarcin Wojtas if (unlikely(!io_sq->entries_in_tx_burst_left)) {
889eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
899eb1615fSMarcin Wojtas "Error: trying to send more packets than tx burst allows\n");
9067ec48bbSMarcin Wojtas return ENA_COM_NO_SPACE;
9167ec48bbSMarcin Wojtas }
9267ec48bbSMarcin Wojtas
9367ec48bbSMarcin Wojtas io_sq->entries_in_tx_burst_left--;
949eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
959eb1615fSMarcin Wojtas "Decreasing entries_in_tx_burst_left of queue %d to %d\n",
9667ec48bbSMarcin Wojtas io_sq->qid, io_sq->entries_in_tx_burst_left);
9767ec48bbSMarcin Wojtas }
9867ec48bbSMarcin Wojtas
99a195fab0SMarcin Wojtas /* Make sure everything was written into the bounce buffer before
100a195fab0SMarcin Wojtas * writing the bounce buffer to the device
101a195fab0SMarcin Wojtas */
102a195fab0SMarcin Wojtas wmb();
103a195fab0SMarcin Wojtas
104a195fab0SMarcin Wojtas /* The line is completed. Copy it to dev */
105*f5f8d7c9SOsama Abboud ENA_MEMCPY_TO_DEVICE_64(io_sq->bus,
106*f5f8d7c9SOsama Abboud io_sq->desc_addr.pbuf_dev_addr + dst_offset,
107a195fab0SMarcin Wojtas bounce_buffer,
108a195fab0SMarcin Wojtas llq_info->desc_list_entry_size);
109a195fab0SMarcin Wojtas
11045c98dacSZbigniew Bodek io_sq->tail++;
11145c98dacSZbigniew Bodek
11245c98dacSZbigniew Bodek /* Switch phase bit in case of wrap around */
11345c98dacSZbigniew Bodek if (unlikely((io_sq->tail & (io_sq->q_depth - 1)) == 0))
11445c98dacSZbigniew Bodek io_sq->phase ^= 1;
11567ec48bbSMarcin Wojtas
11667ec48bbSMarcin Wojtas return ENA_COM_OK;
11745c98dacSZbigniew Bodek }
11845c98dacSZbigniew Bodek
ena_com_write_header_to_bounce(struct ena_com_io_sq * io_sq,u8 * header_src,u16 header_len)1198483b844SMarcin Wojtas static int ena_com_write_header_to_bounce(struct ena_com_io_sq *io_sq,
120a195fab0SMarcin Wojtas u8 *header_src,
121a195fab0SMarcin Wojtas u16 header_len)
12245c98dacSZbigniew Bodek {
123a195fab0SMarcin Wojtas struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
124a195fab0SMarcin Wojtas struct ena_com_llq_info *llq_info = &io_sq->llq_info;
125a195fab0SMarcin Wojtas u8 *bounce_buffer = pkt_ctrl->curr_bounce_buf;
126a195fab0SMarcin Wojtas u16 header_offset;
12745c98dacSZbigniew Bodek
12867ec48bbSMarcin Wojtas if (unlikely(io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST))
12945c98dacSZbigniew Bodek return 0;
13045c98dacSZbigniew Bodek
131a195fab0SMarcin Wojtas header_offset =
132a195fab0SMarcin Wojtas llq_info->descs_num_before_header * io_sq->desc_entry_size;
133a195fab0SMarcin Wojtas
134a195fab0SMarcin Wojtas if (unlikely((header_offset + header_len) > llq_info->desc_list_entry_size)) {
1359eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
1369eb1615fSMarcin Wojtas "Trying to write header larger than llq entry can accommodate\n");
137a195fab0SMarcin Wojtas return ENA_COM_FAULT;
13845c98dacSZbigniew Bodek }
13945c98dacSZbigniew Bodek
140a195fab0SMarcin Wojtas if (unlikely(!bounce_buffer)) {
1419eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
1429eb1615fSMarcin Wojtas "Bounce buffer is NULL\n");
143a195fab0SMarcin Wojtas return ENA_COM_FAULT;
144a195fab0SMarcin Wojtas }
145a195fab0SMarcin Wojtas
146a195fab0SMarcin Wojtas memcpy(bounce_buffer + header_offset, header_src, header_len);
14745c98dacSZbigniew Bodek
14845c98dacSZbigniew Bodek return 0;
14945c98dacSZbigniew Bodek }
15045c98dacSZbigniew Bodek
get_sq_desc_llq(struct ena_com_io_sq * io_sq)1518483b844SMarcin Wojtas static void *get_sq_desc_llq(struct ena_com_io_sq *io_sq)
152a195fab0SMarcin Wojtas {
153a195fab0SMarcin Wojtas struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
154a195fab0SMarcin Wojtas u8 *bounce_buffer;
155a195fab0SMarcin Wojtas void *sq_desc;
156a195fab0SMarcin Wojtas
157a195fab0SMarcin Wojtas bounce_buffer = pkt_ctrl->curr_bounce_buf;
158a195fab0SMarcin Wojtas
159a195fab0SMarcin Wojtas if (unlikely(!bounce_buffer)) {
1609eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
1619eb1615fSMarcin Wojtas "Bounce buffer is NULL\n");
162a195fab0SMarcin Wojtas return NULL;
163a195fab0SMarcin Wojtas }
164a195fab0SMarcin Wojtas
165a195fab0SMarcin Wojtas sq_desc = bounce_buffer + pkt_ctrl->idx * io_sq->desc_entry_size;
166a195fab0SMarcin Wojtas pkt_ctrl->idx++;
167a195fab0SMarcin Wojtas pkt_ctrl->descs_left_in_line--;
168a195fab0SMarcin Wojtas
169a195fab0SMarcin Wojtas return sq_desc;
170a195fab0SMarcin Wojtas }
171a195fab0SMarcin Wojtas
ena_com_close_bounce_buffer(struct ena_com_io_sq * io_sq)1728483b844SMarcin Wojtas static int ena_com_close_bounce_buffer(struct ena_com_io_sq *io_sq)
173a195fab0SMarcin Wojtas {
174a195fab0SMarcin Wojtas struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
175a195fab0SMarcin Wojtas struct ena_com_llq_info *llq_info = &io_sq->llq_info;
17667ec48bbSMarcin Wojtas int rc;
177a195fab0SMarcin Wojtas
17867ec48bbSMarcin Wojtas if (unlikely(io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST))
17967ec48bbSMarcin Wojtas return ENA_COM_OK;
180a195fab0SMarcin Wojtas
181a195fab0SMarcin Wojtas /* bounce buffer was used, so write it and get a new one */
1823fc5d816SMarcin Wojtas if (likely(pkt_ctrl->idx)) {
18367ec48bbSMarcin Wojtas rc = ena_com_write_bounce_buffer_to_dev(io_sq,
184a195fab0SMarcin Wojtas pkt_ctrl->curr_bounce_buf);
1858483b844SMarcin Wojtas if (unlikely(rc)) {
1869eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
1879eb1615fSMarcin Wojtas "Failed to write bounce buffer to device\n");
18867ec48bbSMarcin Wojtas return rc;
1898483b844SMarcin Wojtas }
19067ec48bbSMarcin Wojtas
191a195fab0SMarcin Wojtas pkt_ctrl->curr_bounce_buf =
192a195fab0SMarcin Wojtas ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl);
193a195fab0SMarcin Wojtas memset(io_sq->llq_buf_ctrl.curr_bounce_buf,
194a195fab0SMarcin Wojtas 0x0, llq_info->desc_list_entry_size);
195a195fab0SMarcin Wojtas }
196a195fab0SMarcin Wojtas
197a195fab0SMarcin Wojtas pkt_ctrl->idx = 0;
198a195fab0SMarcin Wojtas pkt_ctrl->descs_left_in_line = llq_info->descs_num_before_header;
19967ec48bbSMarcin Wojtas return ENA_COM_OK;
200a195fab0SMarcin Wojtas }
201a195fab0SMarcin Wojtas
get_sq_desc(struct ena_com_io_sq * io_sq)2028483b844SMarcin Wojtas static void *get_sq_desc(struct ena_com_io_sq *io_sq)
203a195fab0SMarcin Wojtas {
204a195fab0SMarcin Wojtas if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
205a195fab0SMarcin Wojtas return get_sq_desc_llq(io_sq);
206a195fab0SMarcin Wojtas
207a195fab0SMarcin Wojtas return get_sq_desc_regular_queue(io_sq);
208a195fab0SMarcin Wojtas }
209a195fab0SMarcin Wojtas
ena_com_sq_update_llq_tail(struct ena_com_io_sq * io_sq)2108483b844SMarcin Wojtas static int ena_com_sq_update_llq_tail(struct ena_com_io_sq *io_sq)
211a195fab0SMarcin Wojtas {
212a195fab0SMarcin Wojtas struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
213a195fab0SMarcin Wojtas struct ena_com_llq_info *llq_info = &io_sq->llq_info;
21467ec48bbSMarcin Wojtas int rc;
215a195fab0SMarcin Wojtas
216a195fab0SMarcin Wojtas if (!pkt_ctrl->descs_left_in_line) {
21767ec48bbSMarcin Wojtas rc = ena_com_write_bounce_buffer_to_dev(io_sq,
218a195fab0SMarcin Wojtas pkt_ctrl->curr_bounce_buf);
2198483b844SMarcin Wojtas if (unlikely(rc)) {
2209eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
2219eb1615fSMarcin Wojtas "Failed to write bounce buffer to device\n");
22267ec48bbSMarcin Wojtas return rc;
2238483b844SMarcin Wojtas }
224a195fab0SMarcin Wojtas
225a195fab0SMarcin Wojtas pkt_ctrl->curr_bounce_buf =
226a195fab0SMarcin Wojtas ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl);
227a195fab0SMarcin Wojtas memset(io_sq->llq_buf_ctrl.curr_bounce_buf,
228a195fab0SMarcin Wojtas 0x0, llq_info->desc_list_entry_size);
229a195fab0SMarcin Wojtas
230a195fab0SMarcin Wojtas pkt_ctrl->idx = 0;
23167ec48bbSMarcin Wojtas if (unlikely(llq_info->desc_stride_ctrl == ENA_ADMIN_SINGLE_DESC_PER_ENTRY))
232a195fab0SMarcin Wojtas pkt_ctrl->descs_left_in_line = 1;
233a195fab0SMarcin Wojtas else
234a195fab0SMarcin Wojtas pkt_ctrl->descs_left_in_line =
235a195fab0SMarcin Wojtas llq_info->desc_list_entry_size / io_sq->desc_entry_size;
236a195fab0SMarcin Wojtas }
23767ec48bbSMarcin Wojtas
23867ec48bbSMarcin Wojtas return ENA_COM_OK;
239a195fab0SMarcin Wojtas }
240a195fab0SMarcin Wojtas
ena_com_sq_update_reqular_queue_tail(struct ena_com_io_sq * io_sq)241*f5f8d7c9SOsama Abboud static int ena_com_sq_update_reqular_queue_tail(struct ena_com_io_sq *io_sq)
242a195fab0SMarcin Wojtas {
243a195fab0SMarcin Wojtas io_sq->tail++;
244a195fab0SMarcin Wojtas
245a195fab0SMarcin Wojtas /* Switch phase bit in case of wrap around */
246a195fab0SMarcin Wojtas if (unlikely((io_sq->tail & (io_sq->q_depth - 1)) == 0))
247a195fab0SMarcin Wojtas io_sq->phase ^= 1;
24867ec48bbSMarcin Wojtas
24967ec48bbSMarcin Wojtas return ENA_COM_OK;
250a195fab0SMarcin Wojtas }
251a195fab0SMarcin Wojtas
ena_com_sq_update_tail(struct ena_com_io_sq * io_sq)252*f5f8d7c9SOsama Abboud static int ena_com_sq_update_tail(struct ena_com_io_sq *io_sq)
253*f5f8d7c9SOsama Abboud {
254*f5f8d7c9SOsama Abboud if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
255*f5f8d7c9SOsama Abboud return ena_com_sq_update_llq_tail(io_sq);
256*f5f8d7c9SOsama Abboud
257*f5f8d7c9SOsama Abboud return ena_com_sq_update_reqular_queue_tail(io_sq);
258*f5f8d7c9SOsama Abboud }
259*f5f8d7c9SOsama Abboud
2608483b844SMarcin Wojtas static struct ena_eth_io_rx_cdesc_base *
ena_com_rx_cdesc_idx_to_ptr(struct ena_com_io_cq * io_cq,u16 idx)26145c98dacSZbigniew Bodek ena_com_rx_cdesc_idx_to_ptr(struct ena_com_io_cq *io_cq, u16 idx)
26245c98dacSZbigniew Bodek {
26345c98dacSZbigniew Bodek idx &= (io_cq->q_depth - 1);
26445c98dacSZbigniew Bodek return (struct ena_eth_io_rx_cdesc_base *)
26545c98dacSZbigniew Bodek ((uintptr_t)io_cq->cdesc_addr.virt_addr +
26645c98dacSZbigniew Bodek idx * io_cq->cdesc_entry_size_in_bytes);
26745c98dacSZbigniew Bodek }
26845c98dacSZbigniew Bodek
ena_com_cdesc_rx_pkt_get(struct ena_com_io_cq * io_cq,u16 * first_cdesc_idx,u16 * num_descs)269adfed2d8SArthur Kiyanovski static int ena_com_cdesc_rx_pkt_get(struct ena_com_io_cq *io_cq,
270adfed2d8SArthur Kiyanovski u16 *first_cdesc_idx,
271adfed2d8SArthur Kiyanovski u16 *num_descs)
27245c98dacSZbigniew Bodek {
273*f5f8d7c9SOsama Abboud struct ena_com_dev *dev = ena_com_io_cq_to_ena_dev(io_cq);
274adfed2d8SArthur Kiyanovski u16 count = io_cq->cur_rx_pkt_cdesc_count, head_masked;
27545c98dacSZbigniew Bodek struct ena_eth_io_rx_cdesc_base *cdesc;
27645c98dacSZbigniew Bodek u32 last = 0;
27745c98dacSZbigniew Bodek
27845c98dacSZbigniew Bodek do {
279adfed2d8SArthur Kiyanovski u32 status;
280adfed2d8SArthur Kiyanovski
28145c98dacSZbigniew Bodek cdesc = ena_com_get_next_rx_cdesc(io_cq);
28245c98dacSZbigniew Bodek if (!cdesc)
28345c98dacSZbigniew Bodek break;
284adfed2d8SArthur Kiyanovski status = READ_ONCE32(cdesc->status);
28545c98dacSZbigniew Bodek
28645c98dacSZbigniew Bodek ena_com_cq_inc_head(io_cq);
287adfed2d8SArthur Kiyanovski if (unlikely((status & ENA_ETH_IO_RX_CDESC_BASE_FIRST_MASK) >>
288adfed2d8SArthur Kiyanovski ENA_ETH_IO_RX_CDESC_BASE_FIRST_SHIFT && count != 0)) {
289adfed2d8SArthur Kiyanovski ena_trc_err(dev,
290adfed2d8SArthur Kiyanovski "First bit is on in descriptor #%d on q_id: %d, req_id: %u\n",
291adfed2d8SArthur Kiyanovski count, io_cq->qid, cdesc->req_id);
292adfed2d8SArthur Kiyanovski return ENA_COM_FAULT;
293adfed2d8SArthur Kiyanovski }
294*f5f8d7c9SOsama Abboud
295*f5f8d7c9SOsama Abboud if (unlikely((status & (ENA_ETH_IO_RX_CDESC_BASE_MBZ7_MASK |
296*f5f8d7c9SOsama Abboud ENA_ETH_IO_RX_CDESC_BASE_MBZ17_MASK)) &&
297*f5f8d7c9SOsama Abboud ena_com_get_cap(dev, ENA_ADMIN_CDESC_MBZ))) {
298*f5f8d7c9SOsama Abboud ena_trc_err(dev,
299*f5f8d7c9SOsama Abboud "Corrupted RX descriptor #%d on q_id: %d, req_id: %u\n",
300*f5f8d7c9SOsama Abboud count, io_cq->qid, cdesc->req_id);
301*f5f8d7c9SOsama Abboud return ENA_COM_FAULT;
302*f5f8d7c9SOsama Abboud }
303*f5f8d7c9SOsama Abboud
30445c98dacSZbigniew Bodek count++;
305adfed2d8SArthur Kiyanovski last = (status & ENA_ETH_IO_RX_CDESC_BASE_LAST_MASK) >>
30645c98dacSZbigniew Bodek ENA_ETH_IO_RX_CDESC_BASE_LAST_SHIFT;
30745c98dacSZbigniew Bodek } while (!last);
30845c98dacSZbigniew Bodek
30945c98dacSZbigniew Bodek if (last) {
31045c98dacSZbigniew Bodek *first_cdesc_idx = io_cq->cur_rx_pkt_cdesc_start_idx;
31145c98dacSZbigniew Bodek
31245c98dacSZbigniew Bodek head_masked = io_cq->head & (io_cq->q_depth - 1);
31345c98dacSZbigniew Bodek
314adfed2d8SArthur Kiyanovski *num_descs = count;
31545c98dacSZbigniew Bodek io_cq->cur_rx_pkt_cdesc_count = 0;
31645c98dacSZbigniew Bodek io_cq->cur_rx_pkt_cdesc_start_idx = head_masked;
31745c98dacSZbigniew Bodek
3189eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
3199eb1615fSMarcin Wojtas "ENA q_id: %d packets were completed. first desc idx %u descs# %d\n",
32045c98dacSZbigniew Bodek io_cq->qid, *first_cdesc_idx, count);
32145c98dacSZbigniew Bodek } else {
322adfed2d8SArthur Kiyanovski io_cq->cur_rx_pkt_cdesc_count = count;
323adfed2d8SArthur Kiyanovski *num_descs = 0;
32445c98dacSZbigniew Bodek }
32545c98dacSZbigniew Bodek
326adfed2d8SArthur Kiyanovski return ENA_COM_OK;
32745c98dacSZbigniew Bodek }
32845c98dacSZbigniew Bodek
ena_com_create_meta(struct ena_com_io_sq * io_sq,struct ena_com_tx_meta * ena_meta)3298483b844SMarcin Wojtas static int ena_com_create_meta(struct ena_com_io_sq *io_sq,
3308483b844SMarcin Wojtas struct ena_com_tx_meta *ena_meta)
33145c98dacSZbigniew Bodek {
33245c98dacSZbigniew Bodek struct ena_eth_io_tx_meta_desc *meta_desc = NULL;
33345c98dacSZbigniew Bodek
33445c98dacSZbigniew Bodek meta_desc = get_sq_desc(io_sq);
3359eb1615fSMarcin Wojtas if (unlikely(!meta_desc))
3369eb1615fSMarcin Wojtas return ENA_COM_FAULT;
3379eb1615fSMarcin Wojtas
33845c98dacSZbigniew Bodek memset(meta_desc, 0x0, sizeof(struct ena_eth_io_tx_meta_desc));
33945c98dacSZbigniew Bodek
34045c98dacSZbigniew Bodek meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_DESC_MASK;
34145c98dacSZbigniew Bodek
34245c98dacSZbigniew Bodek meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_EXT_VALID_MASK;
34345c98dacSZbigniew Bodek
34445c98dacSZbigniew Bodek /* bits 0-9 of the mss */
3459eb1615fSMarcin Wojtas meta_desc->word2 |= ((u32)ena_meta->mss <<
34645c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_MSS_LO_SHIFT) &
34745c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_MSS_LO_MASK;
34845c98dacSZbigniew Bodek /* bits 10-13 of the mss */
34945c98dacSZbigniew Bodek meta_desc->len_ctrl |= ((ena_meta->mss >> 10) <<
35045c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_MSS_HI_SHIFT) &
35145c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_MSS_HI_MASK;
35245c98dacSZbigniew Bodek
35345c98dacSZbigniew Bodek /* Extended meta desc */
35445c98dacSZbigniew Bodek meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_ETH_META_TYPE_MASK;
3559eb1615fSMarcin Wojtas meta_desc->len_ctrl |= ((u32)io_sq->phase <<
35645c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_PHASE_SHIFT) &
35745c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_PHASE_MASK;
35845c98dacSZbigniew Bodek
35945c98dacSZbigniew Bodek meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_FIRST_MASK;
3608483b844SMarcin Wojtas meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_STORE_MASK;
3618483b844SMarcin Wojtas
36245c98dacSZbigniew Bodek meta_desc->word2 |= ena_meta->l3_hdr_len &
36345c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_L3_HDR_LEN_MASK;
36445c98dacSZbigniew Bodek meta_desc->word2 |= (ena_meta->l3_hdr_offset <<
36545c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_L3_HDR_OFF_SHIFT) &
36645c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_L3_HDR_OFF_MASK;
36745c98dacSZbigniew Bodek
3689eb1615fSMarcin Wojtas meta_desc->word2 |= ((u32)ena_meta->l4_hdr_len <<
36945c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_L4_HDR_LEN_IN_WORDS_SHIFT) &
37045c98dacSZbigniew Bodek ENA_ETH_IO_TX_META_DESC_L4_HDR_LEN_IN_WORDS_MASK;
37145c98dacSZbigniew Bodek
37267ec48bbSMarcin Wojtas return ena_com_sq_update_tail(io_sq);
37345c98dacSZbigniew Bodek }
37445c98dacSZbigniew Bodek
ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq * io_sq,struct ena_com_tx_ctx * ena_tx_ctx,bool * have_meta)3758483b844SMarcin Wojtas static int ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq *io_sq,
3768483b844SMarcin Wojtas struct ena_com_tx_ctx *ena_tx_ctx,
3778483b844SMarcin Wojtas bool *have_meta)
3788483b844SMarcin Wojtas {
3798483b844SMarcin Wojtas struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta;
3808483b844SMarcin Wojtas
3818483b844SMarcin Wojtas /* When disable meta caching is set, don't bother to save the meta and
3828483b844SMarcin Wojtas * compare it to the stored version, just create the meta
3838483b844SMarcin Wojtas */
3848483b844SMarcin Wojtas if (io_sq->disable_meta_caching) {
3858483b844SMarcin Wojtas *have_meta = true;
3868483b844SMarcin Wojtas return ena_com_create_meta(io_sq, ena_meta);
3879eb1615fSMarcin Wojtas }
3889eb1615fSMarcin Wojtas
3899eb1615fSMarcin Wojtas if (ena_com_meta_desc_changed(io_sq, ena_tx_ctx)) {
3908483b844SMarcin Wojtas *have_meta = true;
3918483b844SMarcin Wojtas /* Cache the meta desc */
3928483b844SMarcin Wojtas memcpy(&io_sq->cached_tx_meta, ena_meta,
3938483b844SMarcin Wojtas sizeof(struct ena_com_tx_meta));
3948483b844SMarcin Wojtas return ena_com_create_meta(io_sq, ena_meta);
3959eb1615fSMarcin Wojtas }
3969eb1615fSMarcin Wojtas
3978483b844SMarcin Wojtas *have_meta = false;
3988483b844SMarcin Wojtas return ENA_COM_OK;
3998483b844SMarcin Wojtas }
4008483b844SMarcin Wojtas
ena_com_rx_set_flags(struct ena_com_io_cq * io_cq,struct ena_com_rx_ctx * ena_rx_ctx,struct ena_eth_io_rx_cdesc_base * cdesc)4019eb1615fSMarcin Wojtas static void ena_com_rx_set_flags(struct ena_com_io_cq *io_cq,
4029eb1615fSMarcin Wojtas struct ena_com_rx_ctx *ena_rx_ctx,
40345c98dacSZbigniew Bodek struct ena_eth_io_rx_cdesc_base *cdesc)
40445c98dacSZbigniew Bodek {
40545c98dacSZbigniew Bodek ena_rx_ctx->l3_proto = cdesc->status &
40645c98dacSZbigniew Bodek ENA_ETH_IO_RX_CDESC_BASE_L3_PROTO_IDX_MASK;
40745c98dacSZbigniew Bodek ena_rx_ctx->l4_proto =
40845c98dacSZbigniew Bodek (cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_L4_PROTO_IDX_MASK) >>
40945c98dacSZbigniew Bodek ENA_ETH_IO_RX_CDESC_BASE_L4_PROTO_IDX_SHIFT;
41045c98dacSZbigniew Bodek ena_rx_ctx->l3_csum_err =
41167ec48bbSMarcin Wojtas !!((cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_L3_CSUM_ERR_MASK) >>
41267ec48bbSMarcin Wojtas ENA_ETH_IO_RX_CDESC_BASE_L3_CSUM_ERR_SHIFT);
41345c98dacSZbigniew Bodek ena_rx_ctx->l4_csum_err =
41467ec48bbSMarcin Wojtas !!((cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_MASK) >>
41567ec48bbSMarcin Wojtas ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_SHIFT);
41667ec48bbSMarcin Wojtas ena_rx_ctx->l4_csum_checked =
41767ec48bbSMarcin Wojtas !!((cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_MASK) >>
41867ec48bbSMarcin Wojtas ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_SHIFT);
41945c98dacSZbigniew Bodek ena_rx_ctx->hash = cdesc->hash;
42045c98dacSZbigniew Bodek ena_rx_ctx->frag =
42145c98dacSZbigniew Bodek (cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_MASK) >>
42245c98dacSZbigniew Bodek ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_SHIFT;
42345c98dacSZbigniew Bodek
4249eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
4259eb1615fSMarcin Wojtas "l3_proto %d l4_proto %d l3_csum_err %d l4_csum_err %d hash %d frag %d cdesc_status %x\n",
42645c98dacSZbigniew Bodek ena_rx_ctx->l3_proto,
42745c98dacSZbigniew Bodek ena_rx_ctx->l4_proto,
42845c98dacSZbigniew Bodek ena_rx_ctx->l3_csum_err,
42945c98dacSZbigniew Bodek ena_rx_ctx->l4_csum_err,
43045c98dacSZbigniew Bodek ena_rx_ctx->hash,
43145c98dacSZbigniew Bodek ena_rx_ctx->frag,
43245c98dacSZbigniew Bodek cdesc->status);
43345c98dacSZbigniew Bodek }
43445c98dacSZbigniew Bodek
43545c98dacSZbigniew Bodek /*****************************************************************************/
43645c98dacSZbigniew Bodek /***************************** API **********************************/
43745c98dacSZbigniew Bodek /*****************************************************************************/
43845c98dacSZbigniew Bodek
ena_com_prepare_tx(struct ena_com_io_sq * io_sq,struct ena_com_tx_ctx * ena_tx_ctx,int * nb_hw_desc)43945c98dacSZbigniew Bodek int ena_com_prepare_tx(struct ena_com_io_sq *io_sq,
44045c98dacSZbigniew Bodek struct ena_com_tx_ctx *ena_tx_ctx,
44145c98dacSZbigniew Bodek int *nb_hw_desc)
44245c98dacSZbigniew Bodek {
44345c98dacSZbigniew Bodek struct ena_eth_io_tx_desc *desc = NULL;
44445c98dacSZbigniew Bodek struct ena_com_buf *ena_bufs = ena_tx_ctx->ena_bufs;
445a195fab0SMarcin Wojtas void *buffer_to_push = ena_tx_ctx->push_header;
44645c98dacSZbigniew Bodek u16 header_len = ena_tx_ctx->header_len;
44745c98dacSZbigniew Bodek u16 num_bufs = ena_tx_ctx->num_bufs;
448a195fab0SMarcin Wojtas u16 start_tail = io_sq->tail;
449a195fab0SMarcin Wojtas int i, rc;
45045c98dacSZbigniew Bodek bool have_meta;
45145c98dacSZbigniew Bodek u64 addr_hi;
45245c98dacSZbigniew Bodek
45345c98dacSZbigniew Bodek ENA_WARN(io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_TX,
4549eb1615fSMarcin Wojtas ena_com_io_sq_to_ena_dev(io_sq), "wrong Q type");
45545c98dacSZbigniew Bodek
45645c98dacSZbigniew Bodek /* num_bufs +1 for potential meta desc */
45767ec48bbSMarcin Wojtas if (unlikely(!ena_com_sq_have_enough_space(io_sq, num_bufs + 1))) {
4589eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
4599eb1615fSMarcin Wojtas "Not enough space in the tx queue\n");
46045c98dacSZbigniew Bodek return ENA_COM_NO_MEM;
46145c98dacSZbigniew Bodek }
46245c98dacSZbigniew Bodek
46345c98dacSZbigniew Bodek if (unlikely(header_len > io_sq->tx_max_header_size)) {
4649eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
4659eb1615fSMarcin Wojtas "Header size is too large %d max header: %d\n",
46645c98dacSZbigniew Bodek header_len, io_sq->tx_max_header_size);
46745c98dacSZbigniew Bodek return ENA_COM_INVAL;
46845c98dacSZbigniew Bodek }
46945c98dacSZbigniew Bodek
47067ec48bbSMarcin Wojtas if (unlikely(io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV
4718483b844SMarcin Wojtas && !buffer_to_push)) {
4729eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
473adfed2d8SArthur Kiyanovski "Push header wasn't provided in LLQ mode\n");
474a195fab0SMarcin Wojtas return ENA_COM_INVAL;
4758483b844SMarcin Wojtas }
476a195fab0SMarcin Wojtas
477a195fab0SMarcin Wojtas rc = ena_com_write_header_to_bounce(io_sq, buffer_to_push, header_len);
47845c98dacSZbigniew Bodek if (unlikely(rc))
47945c98dacSZbigniew Bodek return rc;
48045c98dacSZbigniew Bodek
4818483b844SMarcin Wojtas rc = ena_com_create_and_store_tx_meta_desc(io_sq, ena_tx_ctx, &have_meta);
4828483b844SMarcin Wojtas if (unlikely(rc)) {
4839eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
4849eb1615fSMarcin Wojtas "Failed to create and store tx meta desc\n");
48567ec48bbSMarcin Wojtas return rc;
48667ec48bbSMarcin Wojtas }
48745c98dacSZbigniew Bodek
48867ec48bbSMarcin Wojtas /* If the caller doesn't want to send packets */
48945c98dacSZbigniew Bodek if (unlikely(!num_bufs && !header_len)) {
49067ec48bbSMarcin Wojtas rc = ena_com_close_bounce_buffer(io_sq);
491*f5f8d7c9SOsama Abboud if (unlikely(rc))
4929eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
4939eb1615fSMarcin Wojtas "Failed to write buffers to LLQ\n");
494a195fab0SMarcin Wojtas *nb_hw_desc = io_sq->tail - start_tail;
49567ec48bbSMarcin Wojtas return rc;
49645c98dacSZbigniew Bodek }
49745c98dacSZbigniew Bodek
49845c98dacSZbigniew Bodek desc = get_sq_desc(io_sq);
499a195fab0SMarcin Wojtas if (unlikely(!desc))
500a195fab0SMarcin Wojtas return ENA_COM_FAULT;
50145c98dacSZbigniew Bodek memset(desc, 0x0, sizeof(struct ena_eth_io_tx_desc));
50245c98dacSZbigniew Bodek
50345c98dacSZbigniew Bodek /* Set first desc when we don't have meta descriptor */
50445c98dacSZbigniew Bodek if (!have_meta)
50545c98dacSZbigniew Bodek desc->len_ctrl |= ENA_ETH_IO_TX_DESC_FIRST_MASK;
50645c98dacSZbigniew Bodek
5079eb1615fSMarcin Wojtas desc->buff_addr_hi_hdr_sz |= ((u32)header_len <<
50845c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_HEADER_LENGTH_SHIFT) &
50945c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_HEADER_LENGTH_MASK;
5109eb1615fSMarcin Wojtas desc->len_ctrl |= ((u32)io_sq->phase << ENA_ETH_IO_TX_DESC_PHASE_SHIFT) &
51145c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_PHASE_MASK;
51245c98dacSZbigniew Bodek
51345c98dacSZbigniew Bodek desc->len_ctrl |= ENA_ETH_IO_TX_DESC_COMP_REQ_MASK;
51445c98dacSZbigniew Bodek
51545c98dacSZbigniew Bodek /* Bits 0-9 */
5169eb1615fSMarcin Wojtas desc->meta_ctrl |= ((u32)ena_tx_ctx->req_id <<
51745c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_REQ_ID_LO_SHIFT) &
51845c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_REQ_ID_LO_MASK;
51945c98dacSZbigniew Bodek
52045c98dacSZbigniew Bodek desc->meta_ctrl |= (ena_tx_ctx->df <<
52145c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_DF_SHIFT) &
52245c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_DF_MASK;
52345c98dacSZbigniew Bodek
52445c98dacSZbigniew Bodek /* Bits 10-15 */
52545c98dacSZbigniew Bodek desc->len_ctrl |= ((ena_tx_ctx->req_id >> 10) <<
52645c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_REQ_ID_HI_SHIFT) &
52745c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_REQ_ID_HI_MASK;
52845c98dacSZbigniew Bodek
52945c98dacSZbigniew Bodek if (ena_tx_ctx->meta_valid) {
53045c98dacSZbigniew Bodek desc->meta_ctrl |= (ena_tx_ctx->tso_enable <<
53145c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_TSO_EN_SHIFT) &
53245c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_TSO_EN_MASK;
53345c98dacSZbigniew Bodek desc->meta_ctrl |= ena_tx_ctx->l3_proto &
53445c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L3_PROTO_IDX_MASK;
53545c98dacSZbigniew Bodek desc->meta_ctrl |= (ena_tx_ctx->l4_proto <<
53645c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L4_PROTO_IDX_SHIFT) &
53745c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L4_PROTO_IDX_MASK;
53845c98dacSZbigniew Bodek desc->meta_ctrl |= (ena_tx_ctx->l3_csum_enable <<
53945c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L3_CSUM_EN_SHIFT) &
54045c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L3_CSUM_EN_MASK;
54145c98dacSZbigniew Bodek desc->meta_ctrl |= (ena_tx_ctx->l4_csum_enable <<
54245c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L4_CSUM_EN_SHIFT) &
54345c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L4_CSUM_EN_MASK;
54445c98dacSZbigniew Bodek desc->meta_ctrl |= (ena_tx_ctx->l4_csum_partial <<
54545c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L4_CSUM_PARTIAL_SHIFT) &
54645c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_L4_CSUM_PARTIAL_MASK;
54745c98dacSZbigniew Bodek }
54845c98dacSZbigniew Bodek
54945c98dacSZbigniew Bodek for (i = 0; i < num_bufs; i++) {
55045c98dacSZbigniew Bodek /* The first desc share the same desc as the header */
55145c98dacSZbigniew Bodek if (likely(i != 0)) {
55267ec48bbSMarcin Wojtas rc = ena_com_sq_update_tail(io_sq);
5538483b844SMarcin Wojtas if (unlikely(rc)) {
5549eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
5559eb1615fSMarcin Wojtas "Failed to update sq tail\n");
55667ec48bbSMarcin Wojtas return rc;
5578483b844SMarcin Wojtas }
55845c98dacSZbigniew Bodek
55945c98dacSZbigniew Bodek desc = get_sq_desc(io_sq);
560a195fab0SMarcin Wojtas if (unlikely(!desc))
561a195fab0SMarcin Wojtas return ENA_COM_FAULT;
562a195fab0SMarcin Wojtas
56345c98dacSZbigniew Bodek memset(desc, 0x0, sizeof(struct ena_eth_io_tx_desc));
56445c98dacSZbigniew Bodek
5659eb1615fSMarcin Wojtas desc->len_ctrl |= ((u32)io_sq->phase <<
56645c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_PHASE_SHIFT) &
56745c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_PHASE_MASK;
56845c98dacSZbigniew Bodek }
56945c98dacSZbigniew Bodek
57045c98dacSZbigniew Bodek desc->len_ctrl |= ena_bufs->len &
57145c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_LENGTH_MASK;
57245c98dacSZbigniew Bodek
57345c98dacSZbigniew Bodek addr_hi = ((ena_bufs->paddr &
57445c98dacSZbigniew Bodek GENMASK_ULL(io_sq->dma_addr_bits - 1, 32)) >> 32);
57545c98dacSZbigniew Bodek
57645c98dacSZbigniew Bodek desc->buff_addr_lo = (u32)ena_bufs->paddr;
57745c98dacSZbigniew Bodek desc->buff_addr_hi_hdr_sz |= addr_hi &
57845c98dacSZbigniew Bodek ENA_ETH_IO_TX_DESC_ADDR_HI_MASK;
57945c98dacSZbigniew Bodek ena_bufs++;
58045c98dacSZbigniew Bodek }
58145c98dacSZbigniew Bodek
58245c98dacSZbigniew Bodek /* set the last desc indicator */
58345c98dacSZbigniew Bodek desc->len_ctrl |= ENA_ETH_IO_TX_DESC_LAST_MASK;
58445c98dacSZbigniew Bodek
58567ec48bbSMarcin Wojtas rc = ena_com_sq_update_tail(io_sq);
5868483b844SMarcin Wojtas if (unlikely(rc)) {
5879eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
5889eb1615fSMarcin Wojtas "Failed to update sq tail of the last descriptor\n");
58967ec48bbSMarcin Wojtas return rc;
5908483b844SMarcin Wojtas }
59145c98dacSZbigniew Bodek
59267ec48bbSMarcin Wojtas rc = ena_com_close_bounce_buffer(io_sq);
59345c98dacSZbigniew Bodek
594a195fab0SMarcin Wojtas *nb_hw_desc = io_sq->tail - start_tail;
59567ec48bbSMarcin Wojtas return rc;
59645c98dacSZbigniew Bodek }
59745c98dacSZbigniew Bodek
ena_com_rx_pkt(struct ena_com_io_cq * io_cq,struct ena_com_io_sq * io_sq,struct ena_com_rx_ctx * ena_rx_ctx)59845c98dacSZbigniew Bodek int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
59945c98dacSZbigniew Bodek struct ena_com_io_sq *io_sq,
60045c98dacSZbigniew Bodek struct ena_com_rx_ctx *ena_rx_ctx)
60145c98dacSZbigniew Bodek {
60245c98dacSZbigniew Bodek struct ena_com_rx_buf_info *ena_buf = &ena_rx_ctx->ena_bufs[0];
60345c98dacSZbigniew Bodek struct ena_eth_io_rx_cdesc_base *cdesc = NULL;
6049eb1615fSMarcin Wojtas u16 q_depth = io_cq->q_depth;
60545c98dacSZbigniew Bodek u16 cdesc_idx = 0;
60645c98dacSZbigniew Bodek u16 nb_hw_desc;
6078483b844SMarcin Wojtas u16 i = 0;
608adfed2d8SArthur Kiyanovski int rc;
60945c98dacSZbigniew Bodek
61045c98dacSZbigniew Bodek ENA_WARN(io_cq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX,
6119eb1615fSMarcin Wojtas ena_com_io_cq_to_ena_dev(io_cq), "wrong Q type");
61245c98dacSZbigniew Bodek
613adfed2d8SArthur Kiyanovski rc = ena_com_cdesc_rx_pkt_get(io_cq, &cdesc_idx, &nb_hw_desc);
614adfed2d8SArthur Kiyanovski if (unlikely(rc != ENA_COM_OK))
615adfed2d8SArthur Kiyanovski return ENA_COM_FAULT;
616adfed2d8SArthur Kiyanovski
61745c98dacSZbigniew Bodek if (nb_hw_desc == 0) {
61845c98dacSZbigniew Bodek ena_rx_ctx->descs = nb_hw_desc;
61945c98dacSZbigniew Bodek return 0;
62045c98dacSZbigniew Bodek }
62145c98dacSZbigniew Bodek
6229eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
6239eb1615fSMarcin Wojtas "Fetch rx packet: queue %d completed desc: %d\n",
62445c98dacSZbigniew Bodek io_cq->qid, nb_hw_desc);
62545c98dacSZbigniew Bodek
62645c98dacSZbigniew Bodek if (unlikely(nb_hw_desc > ena_rx_ctx->max_bufs)) {
6279eb1615fSMarcin Wojtas ena_trc_err(ena_com_io_cq_to_ena_dev(io_cq),
6289eb1615fSMarcin Wojtas "Too many RX cdescs (%d) > MAX(%d)\n",
62945c98dacSZbigniew Bodek nb_hw_desc, ena_rx_ctx->max_bufs);
63045c98dacSZbigniew Bodek return ENA_COM_NO_SPACE;
63145c98dacSZbigniew Bodek }
63245c98dacSZbigniew Bodek
6338483b844SMarcin Wojtas cdesc = ena_com_rx_cdesc_idx_to_ptr(io_cq, cdesc_idx);
6348483b844SMarcin Wojtas ena_rx_ctx->pkt_offset = cdesc->offset;
63545c98dacSZbigniew Bodek
6368483b844SMarcin Wojtas do {
6379eb1615fSMarcin Wojtas ena_buf[i].len = cdesc->length;
6389eb1615fSMarcin Wojtas ena_buf[i].req_id = cdesc->req_id;
6399eb1615fSMarcin Wojtas if (unlikely(ena_buf[i].req_id >= q_depth))
6409eb1615fSMarcin Wojtas return ENA_COM_EIO;
6419eb1615fSMarcin Wojtas
6429eb1615fSMarcin Wojtas if (++i >= nb_hw_desc)
6439eb1615fSMarcin Wojtas break;
6449eb1615fSMarcin Wojtas
6459eb1615fSMarcin Wojtas cdesc = ena_com_rx_cdesc_idx_to_ptr(io_cq, cdesc_idx + i);
6469eb1615fSMarcin Wojtas
6479eb1615fSMarcin Wojtas } while (1);
64845c98dacSZbigniew Bodek
64945c98dacSZbigniew Bodek /* Update SQ head ptr */
65045c98dacSZbigniew Bodek io_sq->next_to_comp += nb_hw_desc;
65145c98dacSZbigniew Bodek
6529eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
6539eb1615fSMarcin Wojtas "[%s][QID#%d] Updating SQ head to: %d\n", __func__,
65445c98dacSZbigniew Bodek io_sq->qid, io_sq->next_to_comp);
65545c98dacSZbigniew Bodek
65645c98dacSZbigniew Bodek /* Get rx flags from the last pkt */
6579eb1615fSMarcin Wojtas ena_com_rx_set_flags(io_cq, ena_rx_ctx, cdesc);
65845c98dacSZbigniew Bodek
65945c98dacSZbigniew Bodek ena_rx_ctx->descs = nb_hw_desc;
6609eb1615fSMarcin Wojtas
66145c98dacSZbigniew Bodek return 0;
66245c98dacSZbigniew Bodek }
66345c98dacSZbigniew Bodek
ena_com_add_single_rx_desc(struct ena_com_io_sq * io_sq,struct ena_com_buf * ena_buf,u16 req_id)66445c98dacSZbigniew Bodek int ena_com_add_single_rx_desc(struct ena_com_io_sq *io_sq,
66545c98dacSZbigniew Bodek struct ena_com_buf *ena_buf,
66645c98dacSZbigniew Bodek u16 req_id)
66745c98dacSZbigniew Bodek {
66845c98dacSZbigniew Bodek struct ena_eth_io_rx_desc *desc;
66945c98dacSZbigniew Bodek
67045c98dacSZbigniew Bodek ENA_WARN(io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX,
6719eb1615fSMarcin Wojtas ena_com_io_sq_to_ena_dev(io_sq), "wrong Q type");
67245c98dacSZbigniew Bodek
673a195fab0SMarcin Wojtas if (unlikely(!ena_com_sq_have_enough_space(io_sq, 1)))
67445c98dacSZbigniew Bodek return ENA_COM_NO_SPACE;
67545c98dacSZbigniew Bodek
676*f5f8d7c9SOsama Abboud /* virt_addr allocation success is checked before calling this function */
677*f5f8d7c9SOsama Abboud desc = get_sq_desc_regular_queue(io_sq);
678a195fab0SMarcin Wojtas
67945c98dacSZbigniew Bodek memset(desc, 0x0, sizeof(struct ena_eth_io_rx_desc));
68045c98dacSZbigniew Bodek
68145c98dacSZbigniew Bodek desc->length = ena_buf->len;
68245c98dacSZbigniew Bodek
68367ec48bbSMarcin Wojtas desc->ctrl = ENA_ETH_IO_RX_DESC_FIRST_MASK |
68467ec48bbSMarcin Wojtas ENA_ETH_IO_RX_DESC_LAST_MASK |
6859eb1615fSMarcin Wojtas ENA_ETH_IO_RX_DESC_COMP_REQ_MASK |
6869eb1615fSMarcin Wojtas (io_sq->phase & ENA_ETH_IO_RX_DESC_PHASE_MASK);
68745c98dacSZbigniew Bodek
68845c98dacSZbigniew Bodek desc->req_id = req_id;
68945c98dacSZbigniew Bodek
6909eb1615fSMarcin Wojtas ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
6919eb1615fSMarcin Wojtas "[%s] Adding single RX desc, Queue: %u, req_id: %u\n",
6929eb1615fSMarcin Wojtas __func__, io_sq->qid, req_id);
6939eb1615fSMarcin Wojtas
69445c98dacSZbigniew Bodek desc->buff_addr_lo = (u32)ena_buf->paddr;
69545c98dacSZbigniew Bodek desc->buff_addr_hi =
69645c98dacSZbigniew Bodek ((ena_buf->paddr & GENMASK_ULL(io_sq->dma_addr_bits - 1, 32)) >> 32);
69745c98dacSZbigniew Bodek
698*f5f8d7c9SOsama Abboud return ena_com_sq_update_reqular_queue_tail(io_sq);
69945c98dacSZbigniew Bodek }
70045c98dacSZbigniew Bodek
ena_com_cq_empty(struct ena_com_io_cq * io_cq)70167ec48bbSMarcin Wojtas bool ena_com_cq_empty(struct ena_com_io_cq *io_cq)
70245c98dacSZbigniew Bodek {
70367ec48bbSMarcin Wojtas struct ena_eth_io_rx_cdesc_base *cdesc;
70445c98dacSZbigniew Bodek
70567ec48bbSMarcin Wojtas cdesc = ena_com_get_next_rx_cdesc(io_cq);
70667ec48bbSMarcin Wojtas if (cdesc)
70767ec48bbSMarcin Wojtas return false;
70867ec48bbSMarcin Wojtas else
70967ec48bbSMarcin Wojtas return true;
71045c98dacSZbigniew Bodek }
711