1*95eaa71cSShai Brandes /* SPDX-License-Identifier: BSD-3-Clause */
2*95eaa71cSShai Brandes /* Copyright (c) Amazon.com, Inc. or its affiliates.
399ecfbf8SJan Medala * All rights reserved.
499ecfbf8SJan Medala */
599ecfbf8SJan Medala
699ecfbf8SJan Medala #include "ena_eth_com.h"
799ecfbf8SJan Medala
ena_com_get_next_rx_cdesc(struct ena_com_io_cq * io_cq)811866230SShai Brandes struct ena_eth_io_rx_cdesc_base *ena_com_get_next_rx_cdesc(struct ena_com_io_cq *io_cq)
999ecfbf8SJan Medala {
1099ecfbf8SJan Medala struct ena_eth_io_rx_cdesc_base *cdesc;
1199ecfbf8SJan Medala u16 expected_phase, head_masked;
1299ecfbf8SJan Medala u16 desc_phase;
1399ecfbf8SJan Medala
1499ecfbf8SJan Medala head_masked = io_cq->head & (io_cq->q_depth - 1);
1599ecfbf8SJan Medala expected_phase = io_cq->phase;
1699ecfbf8SJan Medala
173adcba9aSMichal Krawczyk cdesc = (struct ena_eth_io_rx_cdesc_base *)(io_cq->cdesc_addr.virt_addr
1899ecfbf8SJan Medala + (head_masked * io_cq->cdesc_entry_size_in_bytes));
1999ecfbf8SJan Medala
20368cbe96SShai Brandes desc_phase = ENA_FIELD_GET(READ_ONCE32(cdesc->status),
21368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK,
22368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_PHASE_SHIFT);
2399ecfbf8SJan Medala
2499ecfbf8SJan Medala if (desc_phase != expected_phase)
2599ecfbf8SJan Medala return NULL;
2699ecfbf8SJan Medala
27b68309beSRafal Kozik /* Make sure we read the rest of the descriptor after the phase bit
28b68309beSRafal Kozik * has been read
29b68309beSRafal Kozik */
30b68309beSRafal Kozik dma_rmb();
31b68309beSRafal Kozik
3299ecfbf8SJan Medala return cdesc;
3399ecfbf8SJan Medala }
3499ecfbf8SJan Medala
ena_com_dump_single_rx_cdesc(struct ena_com_io_cq * io_cq,struct ena_eth_io_rx_cdesc_base * desc)3511866230SShai Brandes void ena_com_dump_single_rx_cdesc(struct ena_com_io_cq *io_cq,
3611866230SShai Brandes struct ena_eth_io_rx_cdesc_base *desc)
3711866230SShai Brandes {
3811866230SShai Brandes if (desc) {
3911866230SShai Brandes uint32_t *desc_arr = (uint32_t *)desc;
4011866230SShai Brandes
4111866230SShai Brandes ena_trc_err(ena_com_io_cq_to_ena_dev(io_cq),
4211866230SShai Brandes "RX descriptor value[0x%08x 0x%08x 0x%08x 0x%08x] phase[%u] first[%u] last[%u] MBZ7[%u] MZB17[%u]\n",
4311866230SShai Brandes desc_arr[0], desc_arr[1], desc_arr[2], desc_arr[3],
4411866230SShai Brandes ENA_FIELD_GET(desc->status, (uint32_t)ENA_ETH_IO_RX_DESC_PHASE_MASK,
4511866230SShai Brandes 0),
4611866230SShai Brandes ENA_FIELD_GET(desc->status, (uint32_t)ENA_ETH_IO_RX_DESC_FIRST_MASK,
4711866230SShai Brandes ENA_ETH_IO_RX_DESC_FIRST_SHIFT),
4811866230SShai Brandes ENA_FIELD_GET(desc->status, (uint32_t)ENA_ETH_IO_RX_DESC_LAST_MASK,
4911866230SShai Brandes ENA_ETH_IO_RX_DESC_LAST_SHIFT),
5011866230SShai Brandes ENA_FIELD_GET(desc->status,
5111866230SShai Brandes (uint32_t)ENA_ETH_IO_RX_CDESC_BASE_MBZ7_MASK,
5211866230SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_MBZ7_SHIFT),
5311866230SShai Brandes ENA_FIELD_GET(desc->status,
5411866230SShai Brandes (uint32_t)ENA_ETH_IO_RX_CDESC_BASE_MBZ17_MASK,
5511866230SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_MBZ17_SHIFT));
5611866230SShai Brandes }
5711866230SShai Brandes }
5811866230SShai Brandes
ena_com_dump_single_tx_cdesc(struct ena_com_io_cq * io_cq,struct ena_eth_io_tx_cdesc * desc)5911866230SShai Brandes void ena_com_dump_single_tx_cdesc(struct ena_com_io_cq *io_cq,
6011866230SShai Brandes struct ena_eth_io_tx_cdesc *desc)
6111866230SShai Brandes {
6211866230SShai Brandes if (desc) {
6311866230SShai Brandes uint32_t *desc_arr = (uint32_t *)desc;
6411866230SShai Brandes
6511866230SShai Brandes ena_trc_err(ena_com_io_cq_to_ena_dev(io_cq),
6611866230SShai Brandes "TX descriptor value[0x%08x 0x%08x] phase[%u] MBZ6[%u]\n",
6711866230SShai Brandes desc_arr[0], desc_arr[1],
6811866230SShai Brandes ENA_FIELD_GET(desc->flags, (uint32_t)ENA_ETH_IO_TX_CDESC_PHASE_MASK,
6911866230SShai Brandes 0),
7011866230SShai Brandes ENA_FIELD_GET(desc->flags, (uint32_t)ENA_ETH_IO_TX_CDESC_MBZ6_MASK,
7111866230SShai Brandes ENA_ETH_IO_TX_CDESC_MBZ6_SHIFT));
7211866230SShai Brandes }
7311866230SShai Brandes }
7411866230SShai Brandes
ena_com_tx_cdesc_idx_to_ptr(struct ena_com_io_cq * io_cq,u16 idx)7511866230SShai Brandes struct ena_eth_io_tx_cdesc *ena_com_tx_cdesc_idx_to_ptr(struct ena_com_io_cq *io_cq, u16 idx)
7611866230SShai Brandes {
7711866230SShai Brandes idx &= (io_cq->q_depth - 1);
7811866230SShai Brandes
7911866230SShai Brandes return (struct ena_eth_io_tx_cdesc *)
8011866230SShai Brandes ((uintptr_t)io_cq->cdesc_addr.virt_addr +
8111866230SShai Brandes idx * io_cq->cdesc_entry_size_in_bytes);
8211866230SShai Brandes }
8311866230SShai Brandes
get_sq_desc_regular_queue(struct ena_com_io_sq * io_sq)84b2b02edeSMichal Krawczyk static void *get_sq_desc_regular_queue(struct ena_com_io_sq *io_sq)
8599ecfbf8SJan Medala {
8699ecfbf8SJan Medala u16 tail_masked;
8799ecfbf8SJan Medala u32 offset;
8899ecfbf8SJan Medala
8999ecfbf8SJan Medala tail_masked = io_sq->tail & (io_sq->q_depth - 1);
9099ecfbf8SJan Medala
9199ecfbf8SJan Medala offset = tail_masked * io_sq->desc_entry_size;
9299ecfbf8SJan Medala
933adcba9aSMichal Krawczyk return (void *)((uintptr_t)io_sq->desc_addr.virt_addr + offset);
9499ecfbf8SJan Medala }
9599ecfbf8SJan Medala
ena_com_write_bounce_buffer_to_dev(struct ena_com_io_sq * io_sq,u8 * bounce_buffer)96b2b02edeSMichal Krawczyk static int ena_com_write_bounce_buffer_to_dev(struct ena_com_io_sq *io_sq,
97b68309beSRafal Kozik u8 *bounce_buffer)
9899ecfbf8SJan Medala {
99b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &io_sq->llq_info;
10099ecfbf8SJan Medala
101b68309beSRafal Kozik u16 dst_tail_mask;
102b68309beSRafal Kozik u32 dst_offset;
10399ecfbf8SJan Medala
104b68309beSRafal Kozik dst_tail_mask = io_sq->tail & (io_sq->q_depth - 1);
105b68309beSRafal Kozik dst_offset = dst_tail_mask * llq_info->desc_list_entry_size;
106b68309beSRafal Kozik
107b68309beSRafal Kozik if (is_llq_max_tx_burst_exists(io_sq)) {
108b2b02edeSMichal Krawczyk if (unlikely(!io_sq->entries_in_tx_burst_left)) {
109ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
110ac2fd8a5SMichal Krawczyk "Error: trying to send more packets than tx burst allows\n");
111b68309beSRafal Kozik return ENA_COM_NO_SPACE;
11299ecfbf8SJan Medala }
11399ecfbf8SJan Medala
114b68309beSRafal Kozik io_sq->entries_in_tx_burst_left--;
115ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
1165c230c36SShai Brandes "Decreasing entries_in_tx_burst_left of queue %u to %u\n",
117b68309beSRafal Kozik io_sq->qid, io_sq->entries_in_tx_burst_left);
118b68309beSRafal Kozik }
119b68309beSRafal Kozik
120b68309beSRafal Kozik /* Make sure everything was written into the bounce buffer before
121b68309beSRafal Kozik * writing the bounce buffer to the device
122b68309beSRafal Kozik */
123b68309beSRafal Kozik wmb();
124b68309beSRafal Kozik
125b68309beSRafal Kozik /* The line is completed. Copy it to dev */
126b68309beSRafal Kozik ENA_MEMCPY_TO_DEVICE_64(io_sq->desc_addr.pbuf_dev_addr + dst_offset,
127b68309beSRafal Kozik bounce_buffer,
128b68309beSRafal Kozik llq_info->desc_list_entry_size);
129b68309beSRafal Kozik
13099ecfbf8SJan Medala io_sq->tail++;
13199ecfbf8SJan Medala
13299ecfbf8SJan Medala /* Switch phase bit in case of wrap around */
13399ecfbf8SJan Medala if (unlikely((io_sq->tail & (io_sq->q_depth - 1)) == 0))
1346dcee7cdSJan Medala io_sq->phase ^= 1;
135b68309beSRafal Kozik
136b68309beSRafal Kozik return ENA_COM_OK;
13799ecfbf8SJan Medala }
13899ecfbf8SJan Medala
ena_com_write_header_to_bounce(struct ena_com_io_sq * io_sq,u8 * header_src,u16 header_len)139b2b02edeSMichal Krawczyk static int ena_com_write_header_to_bounce(struct ena_com_io_sq *io_sq,
140b68309beSRafal Kozik u8 *header_src,
141b68309beSRafal Kozik u16 header_len)
14299ecfbf8SJan Medala {
143b68309beSRafal Kozik struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
144b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &io_sq->llq_info;
145b68309beSRafal Kozik u8 *bounce_buffer = pkt_ctrl->curr_bounce_buf;
146b68309beSRafal Kozik u16 header_offset;
14799ecfbf8SJan Medala
148b2b02edeSMichal Krawczyk if (unlikely(io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST))
14999ecfbf8SJan Medala return 0;
15099ecfbf8SJan Medala
151b68309beSRafal Kozik header_offset =
152b68309beSRafal Kozik llq_info->descs_num_before_header * io_sq->desc_entry_size;
153b68309beSRafal Kozik
154b68309beSRafal Kozik if (unlikely((header_offset + header_len) > llq_info->desc_list_entry_size)) {
155ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
156ac2fd8a5SMichal Krawczyk "Trying to write header larger than llq entry can accommodate\n");
157b68309beSRafal Kozik return ENA_COM_FAULT;
1586dcee7cdSJan Medala }
15999ecfbf8SJan Medala
160b68309beSRafal Kozik if (unlikely(!bounce_buffer)) {
161ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
162ac2fd8a5SMichal Krawczyk "Bounce buffer is NULL\n");
163b68309beSRafal Kozik return ENA_COM_FAULT;
164b68309beSRafal Kozik }
165b68309beSRafal Kozik
166b68309beSRafal Kozik memcpy(bounce_buffer + header_offset, header_src, header_len);
16799ecfbf8SJan Medala
16899ecfbf8SJan Medala return 0;
16999ecfbf8SJan Medala }
17099ecfbf8SJan Medala
get_sq_desc_llq(struct ena_com_io_sq * io_sq)171b2b02edeSMichal Krawczyk static void *get_sq_desc_llq(struct ena_com_io_sq *io_sq)
172b68309beSRafal Kozik {
173b68309beSRafal Kozik struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
174b68309beSRafal Kozik u8 *bounce_buffer;
175b68309beSRafal Kozik void *sq_desc;
176b68309beSRafal Kozik
177b68309beSRafal Kozik bounce_buffer = pkt_ctrl->curr_bounce_buf;
178b68309beSRafal Kozik
179b68309beSRafal Kozik if (unlikely(!bounce_buffer)) {
180ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
181ac2fd8a5SMichal Krawczyk "Bounce buffer is NULL\n");
182b68309beSRafal Kozik return NULL;
183b68309beSRafal Kozik }
184b68309beSRafal Kozik
185b68309beSRafal Kozik sq_desc = bounce_buffer + pkt_ctrl->idx * io_sq->desc_entry_size;
186b68309beSRafal Kozik pkt_ctrl->idx++;
187b68309beSRafal Kozik pkt_ctrl->descs_left_in_line--;
188b68309beSRafal Kozik
189b68309beSRafal Kozik return sq_desc;
190b68309beSRafal Kozik }
191b68309beSRafal Kozik
ena_com_close_bounce_buffer(struct ena_com_io_sq * io_sq)192b2b02edeSMichal Krawczyk static int ena_com_close_bounce_buffer(struct ena_com_io_sq *io_sq)
193b68309beSRafal Kozik {
194b68309beSRafal Kozik struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
195b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &io_sq->llq_info;
196b68309beSRafal Kozik int rc;
197b68309beSRafal Kozik
198b2b02edeSMichal Krawczyk if (unlikely(io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST))
199b68309beSRafal Kozik return ENA_COM_OK;
200b68309beSRafal Kozik
201b68309beSRafal Kozik /* bounce buffer was used, so write it and get a new one */
202f73f53f7SShai Brandes if (likely(pkt_ctrl->idx)) {
203b68309beSRafal Kozik rc = ena_com_write_bounce_buffer_to_dev(io_sq,
204b68309beSRafal Kozik pkt_ctrl->curr_bounce_buf);
20514f3f532SMichal Krawczyk if (unlikely(rc)) {
206ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
207ac2fd8a5SMichal Krawczyk "Failed to write bounce buffer to device\n");
208b68309beSRafal Kozik return rc;
20914f3f532SMichal Krawczyk }
210b68309beSRafal Kozik
211b68309beSRafal Kozik pkt_ctrl->curr_bounce_buf =
212b68309beSRafal Kozik ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl);
213b68309beSRafal Kozik memset(io_sq->llq_buf_ctrl.curr_bounce_buf,
214b68309beSRafal Kozik 0x0, llq_info->desc_list_entry_size);
215b68309beSRafal Kozik }
216b68309beSRafal Kozik
217b68309beSRafal Kozik pkt_ctrl->idx = 0;
218b68309beSRafal Kozik pkt_ctrl->descs_left_in_line = llq_info->descs_num_before_header;
219b68309beSRafal Kozik return ENA_COM_OK;
220b68309beSRafal Kozik }
221b68309beSRafal Kozik
get_sq_desc(struct ena_com_io_sq * io_sq)222b2b02edeSMichal Krawczyk static void *get_sq_desc(struct ena_com_io_sq *io_sq)
223b68309beSRafal Kozik {
224b68309beSRafal Kozik if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
225b68309beSRafal Kozik return get_sq_desc_llq(io_sq);
226b68309beSRafal Kozik
227b68309beSRafal Kozik return get_sq_desc_regular_queue(io_sq);
228b68309beSRafal Kozik }
229b68309beSRafal Kozik
ena_com_sq_update_llq_tail(struct ena_com_io_sq * io_sq)230b2b02edeSMichal Krawczyk static int ena_com_sq_update_llq_tail(struct ena_com_io_sq *io_sq)
231b68309beSRafal Kozik {
232b68309beSRafal Kozik struct ena_com_llq_pkt_ctrl *pkt_ctrl = &io_sq->llq_buf_ctrl;
233b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &io_sq->llq_info;
234b68309beSRafal Kozik int rc;
235b68309beSRafal Kozik
236b68309beSRafal Kozik if (!pkt_ctrl->descs_left_in_line) {
237b68309beSRafal Kozik rc = ena_com_write_bounce_buffer_to_dev(io_sq,
238b68309beSRafal Kozik pkt_ctrl->curr_bounce_buf);
23914f3f532SMichal Krawczyk if (unlikely(rc)) {
240ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
241ac2fd8a5SMichal Krawczyk "Failed to write bounce buffer to device\n");
242b68309beSRafal Kozik return rc;
24314f3f532SMichal Krawczyk }
244b68309beSRafal Kozik
245b68309beSRafal Kozik pkt_ctrl->curr_bounce_buf =
246b68309beSRafal Kozik ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl);
247b68309beSRafal Kozik memset(io_sq->llq_buf_ctrl.curr_bounce_buf,
248b68309beSRafal Kozik 0x0, llq_info->desc_list_entry_size);
249b68309beSRafal Kozik
250b68309beSRafal Kozik pkt_ctrl->idx = 0;
251b2b02edeSMichal Krawczyk if (unlikely(llq_info->desc_stride_ctrl == ENA_ADMIN_SINGLE_DESC_PER_ENTRY))
252b68309beSRafal Kozik pkt_ctrl->descs_left_in_line = 1;
253b68309beSRafal Kozik else
254b68309beSRafal Kozik pkt_ctrl->descs_left_in_line =
255b68309beSRafal Kozik llq_info->desc_list_entry_size / io_sq->desc_entry_size;
256b68309beSRafal Kozik }
257b68309beSRafal Kozik
258b68309beSRafal Kozik return ENA_COM_OK;
259b68309beSRafal Kozik }
260b68309beSRafal Kozik
ena_com_sq_update_reqular_queue_tail(struct ena_com_io_sq * io_sq)2618a344a55SShai Brandes static int ena_com_sq_update_reqular_queue_tail(struct ena_com_io_sq *io_sq)
262b68309beSRafal Kozik {
263b68309beSRafal Kozik io_sq->tail++;
264b68309beSRafal Kozik
265b68309beSRafal Kozik /* Switch phase bit in case of wrap around */
266b68309beSRafal Kozik if (unlikely((io_sq->tail & (io_sq->q_depth - 1)) == 0))
267b68309beSRafal Kozik io_sq->phase ^= 1;
268b68309beSRafal Kozik
269b68309beSRafal Kozik return ENA_COM_OK;
270b68309beSRafal Kozik }
271b68309beSRafal Kozik
ena_com_sq_update_tail(struct ena_com_io_sq * io_sq)2728a344a55SShai Brandes static int ena_com_sq_update_tail(struct ena_com_io_sq *io_sq)
2738a344a55SShai Brandes {
2748a344a55SShai Brandes if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
2758a344a55SShai Brandes return ena_com_sq_update_llq_tail(io_sq);
2768a344a55SShai Brandes
2778a344a55SShai Brandes return ena_com_sq_update_reqular_queue_tail(io_sq);
2788a344a55SShai Brandes }
2798a344a55SShai Brandes
28011866230SShai Brandes struct ena_eth_io_rx_cdesc_base *
ena_com_rx_cdesc_idx_to_ptr(struct ena_com_io_cq * io_cq,u16 idx)28199ecfbf8SJan Medala ena_com_rx_cdesc_idx_to_ptr(struct ena_com_io_cq *io_cq, u16 idx)
28299ecfbf8SJan Medala {
28399ecfbf8SJan Medala idx &= (io_cq->q_depth - 1);
28499ecfbf8SJan Medala return (struct ena_eth_io_rx_cdesc_base *)
2853adcba9aSMichal Krawczyk ((uintptr_t)io_cq->cdesc_addr.virt_addr +
28699ecfbf8SJan Medala idx * io_cq->cdesc_entry_size_in_bytes);
28799ecfbf8SJan Medala }
28899ecfbf8SJan Medala
ena_com_cdesc_rx_pkt_get(struct ena_com_io_cq * io_cq,u16 * first_cdesc_idx,u16 * num_descs)289f73f53f7SShai Brandes static int ena_com_cdesc_rx_pkt_get(struct ena_com_io_cq *io_cq,
290f73f53f7SShai Brandes u16 *first_cdesc_idx,
291f73f53f7SShai Brandes u16 *num_descs)
29299ecfbf8SJan Medala {
293445d6d9aSShai Brandes struct ena_com_dev *dev = ena_com_io_cq_to_ena_dev(io_cq);
294f73f53f7SShai Brandes u16 count = io_cq->cur_rx_pkt_cdesc_count, head_masked;
29599ecfbf8SJan Medala struct ena_eth_io_rx_cdesc_base *cdesc;
29699ecfbf8SJan Medala u32 last = 0;
29799ecfbf8SJan Medala
29899ecfbf8SJan Medala do {
299f73f53f7SShai Brandes u32 status;
300f73f53f7SShai Brandes
30199ecfbf8SJan Medala cdesc = ena_com_get_next_rx_cdesc(io_cq);
30299ecfbf8SJan Medala if (!cdesc)
30399ecfbf8SJan Medala break;
304f73f53f7SShai Brandes status = READ_ONCE32(cdesc->status);
30599ecfbf8SJan Medala
306368cbe96SShai Brandes if (unlikely(ENA_FIELD_GET(status,
307368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_FIRST_MASK,
308368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_FIRST_SHIFT) &&
309368cbe96SShai Brandes count != 0)) {
310f73f53f7SShai Brandes ena_trc_err(dev,
3115c230c36SShai Brandes "First bit is on in descriptor #%u on q_id: %u, req_id: %u\n",
312f73f53f7SShai Brandes count, io_cq->qid, cdesc->req_id);
313f73f53f7SShai Brandes return ENA_COM_FAULT;
314f73f53f7SShai Brandes }
315445d6d9aSShai Brandes
316445d6d9aSShai Brandes if (unlikely((status & (ENA_ETH_IO_RX_CDESC_BASE_MBZ7_MASK |
317445d6d9aSShai Brandes ENA_ETH_IO_RX_CDESC_BASE_MBZ17_MASK)) &&
318445d6d9aSShai Brandes ena_com_get_cap(dev, ENA_ADMIN_CDESC_MBZ))) {
319445d6d9aSShai Brandes ena_trc_err(dev,
3205c230c36SShai Brandes "Corrupted RX descriptor #%u on q_id: %u, req_id: %u\n",
321445d6d9aSShai Brandes count, io_cq->qid, cdesc->req_id);
322445d6d9aSShai Brandes return ENA_COM_FAULT;
323445d6d9aSShai Brandes }
324445d6d9aSShai Brandes
32511866230SShai Brandes ena_com_cq_inc_head(io_cq);
32699ecfbf8SJan Medala count++;
327368cbe96SShai Brandes last = ENA_FIELD_GET(status,
328368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_LAST_MASK,
329368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_LAST_SHIFT);
33099ecfbf8SJan Medala } while (!last);
33199ecfbf8SJan Medala
33299ecfbf8SJan Medala if (last) {
33399ecfbf8SJan Medala *first_cdesc_idx = io_cq->cur_rx_pkt_cdesc_start_idx;
33499ecfbf8SJan Medala
33599ecfbf8SJan Medala head_masked = io_cq->head & (io_cq->q_depth - 1);
33699ecfbf8SJan Medala
337f73f53f7SShai Brandes *num_descs = count;
33899ecfbf8SJan Medala io_cq->cur_rx_pkt_cdesc_count = 0;
33999ecfbf8SJan Medala io_cq->cur_rx_pkt_cdesc_start_idx = head_masked;
34099ecfbf8SJan Medala
341ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
3425c230c36SShai Brandes "ENA q_id: %u packets were completed. first desc idx %u descs# %u\n",
34399ecfbf8SJan Medala io_cq->qid, *first_cdesc_idx, count);
34499ecfbf8SJan Medala } else {
345f73f53f7SShai Brandes io_cq->cur_rx_pkt_cdesc_count = count;
346f73f53f7SShai Brandes *num_descs = 0;
34799ecfbf8SJan Medala }
34899ecfbf8SJan Medala
349f73f53f7SShai Brandes return ENA_COM_OK;
35099ecfbf8SJan Medala }
35199ecfbf8SJan Medala
ena_com_create_meta(struct ena_com_io_sq * io_sq,struct ena_com_tx_meta * ena_meta)352f1453604SMichal Krawczyk static int ena_com_create_meta(struct ena_com_io_sq *io_sq,
353f1453604SMichal Krawczyk struct ena_com_tx_meta *ena_meta)
35499ecfbf8SJan Medala {
35599ecfbf8SJan Medala struct ena_eth_io_tx_meta_desc *meta_desc = NULL;
35699ecfbf8SJan Medala
35799ecfbf8SJan Medala meta_desc = get_sq_desc(io_sq);
3584ad61424SMichal Krawczyk if (unlikely(!meta_desc))
3594ad61424SMichal Krawczyk return ENA_COM_FAULT;
3604ad61424SMichal Krawczyk
36199ecfbf8SJan Medala memset(meta_desc, 0x0, sizeof(struct ena_eth_io_tx_meta_desc));
36299ecfbf8SJan Medala
36399ecfbf8SJan Medala meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_DESC_MASK;
36499ecfbf8SJan Medala
36599ecfbf8SJan Medala meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_EXT_VALID_MASK;
36699ecfbf8SJan Medala
36799ecfbf8SJan Medala /* bits 0-9 of the mss */
368368cbe96SShai Brandes meta_desc->word2 |=
369368cbe96SShai Brandes ENA_FIELD_PREP((u32)ena_meta->mss,
370368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_MSS_LO_MASK,
371368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_MSS_LO_SHIFT);
37299ecfbf8SJan Medala /* bits 10-13 of the mss */
373368cbe96SShai Brandes meta_desc->len_ctrl |=
374368cbe96SShai Brandes ENA_FIELD_PREP((ena_meta->mss >> 10),
375368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_MSS_HI_MASK,
376368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_MSS_HI_SHIFT);
37799ecfbf8SJan Medala
37899ecfbf8SJan Medala /* Extended meta desc */
37999ecfbf8SJan Medala meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_ETH_META_TYPE_MASK;
380368cbe96SShai Brandes meta_desc->len_ctrl |=
381368cbe96SShai Brandes ENA_FIELD_PREP((u32)io_sq->phase,
382368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_PHASE_MASK,
383368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_PHASE_SHIFT);
38499ecfbf8SJan Medala
38599ecfbf8SJan Medala meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_FIRST_MASK;
386f1453604SMichal Krawczyk meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_STORE_MASK;
387f1453604SMichal Krawczyk
38899ecfbf8SJan Medala meta_desc->word2 |= ena_meta->l3_hdr_len &
38999ecfbf8SJan Medala ENA_ETH_IO_TX_META_DESC_L3_HDR_LEN_MASK;
390368cbe96SShai Brandes meta_desc->word2 |=
391368cbe96SShai Brandes ENA_FIELD_PREP(ena_meta->l3_hdr_offset,
392368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_L3_HDR_OFF_MASK,
393368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_L3_HDR_OFF_SHIFT);
39499ecfbf8SJan Medala
395368cbe96SShai Brandes meta_desc->word2 |=
396368cbe96SShai Brandes ENA_FIELD_PREP((u32)ena_meta->l4_hdr_len,
397368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_L4_HDR_LEN_IN_WORDS_MASK,
398368cbe96SShai Brandes ENA_ETH_IO_TX_META_DESC_L4_HDR_LEN_IN_WORDS_SHIFT);
39999ecfbf8SJan Medala
400f1453604SMichal Krawczyk return ena_com_sq_update_tail(io_sq);
401f1453604SMichal Krawczyk }
40299ecfbf8SJan Medala
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)403f1453604SMichal Krawczyk static int ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq *io_sq,
404f1453604SMichal Krawczyk struct ena_com_tx_ctx *ena_tx_ctx,
405f1453604SMichal Krawczyk bool *have_meta)
406f1453604SMichal Krawczyk {
407f1453604SMichal Krawczyk struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta;
408f1453604SMichal Krawczyk
409f1453604SMichal Krawczyk /* When disable meta caching is set, don't bother to save the meta and
410f1453604SMichal Krawczyk * compare it to the stored version, just create the meta
411f1453604SMichal Krawczyk */
412f1453604SMichal Krawczyk if (io_sq->disable_meta_caching) {
413f1453604SMichal Krawczyk *have_meta = true;
414f1453604SMichal Krawczyk return ena_com_create_meta(io_sq, ena_meta);
415b19f366cSMichal Krawczyk }
416b19f366cSMichal Krawczyk
417b19f366cSMichal Krawczyk if (ena_com_meta_desc_changed(io_sq, ena_tx_ctx)) {
418f1453604SMichal Krawczyk *have_meta = true;
419f1453604SMichal Krawczyk /* Cache the meta desc */
42099ecfbf8SJan Medala memcpy(&io_sq->cached_tx_meta, ena_meta,
42199ecfbf8SJan Medala sizeof(struct ena_com_tx_meta));
422f1453604SMichal Krawczyk return ena_com_create_meta(io_sq, ena_meta);
423b19f366cSMichal Krawczyk }
424b19f366cSMichal Krawczyk
425f1453604SMichal Krawczyk *have_meta = false;
426f1453604SMichal Krawczyk return ENA_COM_OK;
427f1453604SMichal Krawczyk }
42899ecfbf8SJan Medala
ena_com_rx_set_flags(struct ena_com_rx_ctx * ena_rx_ctx,struct ena_eth_io_rx_cdesc_base * cdesc)429eea9fc6aSShai Brandes static void ena_com_rx_set_flags(struct ena_com_rx_ctx *ena_rx_ctx,
43099ecfbf8SJan Medala struct ena_eth_io_rx_cdesc_base *cdesc)
43199ecfbf8SJan Medala {
4323adcba9aSMichal Krawczyk ena_rx_ctx->l3_proto = cdesc->status &
4333adcba9aSMichal Krawczyk ENA_ETH_IO_RX_CDESC_BASE_L3_PROTO_IDX_MASK;
4343adcba9aSMichal Krawczyk ena_rx_ctx->l4_proto =
435368cbe96SShai Brandes ENA_FIELD_GET(cdesc->status,
436368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L4_PROTO_IDX_MASK,
437368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L4_PROTO_IDX_SHIFT);
43899ecfbf8SJan Medala ena_rx_ctx->l3_csum_err =
439368cbe96SShai Brandes !!(ENA_FIELD_GET(cdesc->status,
440368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L3_CSUM_ERR_MASK,
441368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L3_CSUM_ERR_SHIFT));
44299ecfbf8SJan Medala ena_rx_ctx->l4_csum_err =
443368cbe96SShai Brandes !!(ENA_FIELD_GET(cdesc->status,
444368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_MASK,
445368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_ERR_SHIFT));
446b68309beSRafal Kozik ena_rx_ctx->l4_csum_checked =
447368cbe96SShai Brandes !!(ENA_FIELD_GET(cdesc->status,
448368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_MASK,
449368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_L4_CSUM_CHECKED_SHIFT));
45099ecfbf8SJan Medala ena_rx_ctx->hash = cdesc->hash;
45199ecfbf8SJan Medala ena_rx_ctx->frag =
452368cbe96SShai Brandes ENA_FIELD_GET(cdesc->status,
453368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_MASK,
454368cbe96SShai Brandes ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_SHIFT);
45599ecfbf8SJan Medala }
45699ecfbf8SJan Medala
45799ecfbf8SJan Medala /*****************************************************************************/
45899ecfbf8SJan Medala /***************************** API **********************************/
45999ecfbf8SJan Medala /*****************************************************************************/
46099ecfbf8SJan Medala
ena_com_prepare_tx(struct ena_com_io_sq * io_sq,struct ena_com_tx_ctx * ena_tx_ctx,int * nb_hw_desc)46199ecfbf8SJan Medala int ena_com_prepare_tx(struct ena_com_io_sq *io_sq,
46299ecfbf8SJan Medala struct ena_com_tx_ctx *ena_tx_ctx,
46399ecfbf8SJan Medala int *nb_hw_desc)
46499ecfbf8SJan Medala {
46599ecfbf8SJan Medala struct ena_eth_io_tx_desc *desc = NULL;
46699ecfbf8SJan Medala struct ena_com_buf *ena_bufs = ena_tx_ctx->ena_bufs;
467b68309beSRafal Kozik void *buffer_to_push = ena_tx_ctx->push_header;
46899ecfbf8SJan Medala u16 header_len = ena_tx_ctx->header_len;
46999ecfbf8SJan Medala u16 num_bufs = ena_tx_ctx->num_bufs;
470b68309beSRafal Kozik u16 start_tail = io_sq->tail;
471b68309beSRafal Kozik int i, rc;
47299ecfbf8SJan Medala bool have_meta;
47399ecfbf8SJan Medala u64 addr_hi;
47499ecfbf8SJan Medala
4753adcba9aSMichal Krawczyk ENA_WARN(io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_TX,
476ac2fd8a5SMichal Krawczyk ena_com_io_sq_to_ena_dev(io_sq), "wrong Q type");
47799ecfbf8SJan Medala
47899ecfbf8SJan Medala /* num_bufs +1 for potential meta desc */
479b2b02edeSMichal Krawczyk if (unlikely(!ena_com_sq_have_enough_space(io_sq, num_bufs + 1))) {
480ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
481ac2fd8a5SMichal Krawczyk "Not enough space in the tx queue\n");
48299ecfbf8SJan Medala return ENA_COM_NO_MEM;
48399ecfbf8SJan Medala }
48499ecfbf8SJan Medala
48599ecfbf8SJan Medala if (unlikely(header_len > io_sq->tx_max_header_size)) {
486ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
4875c230c36SShai Brandes "Header size is too large %u max header: %u\n",
48899ecfbf8SJan Medala header_len, io_sq->tx_max_header_size);
48999ecfbf8SJan Medala return ENA_COM_INVAL;
49099ecfbf8SJan Medala }
49199ecfbf8SJan Medala
492b2b02edeSMichal Krawczyk if (unlikely(io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV
49314f3f532SMichal Krawczyk && !buffer_to_push)) {
494ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
495f73f53f7SShai Brandes "Push header wasn't provided in LLQ mode\n");
496b68309beSRafal Kozik return ENA_COM_INVAL;
49714f3f532SMichal Krawczyk }
498b68309beSRafal Kozik
499b68309beSRafal Kozik rc = ena_com_write_header_to_bounce(io_sq, buffer_to_push, header_len);
50099ecfbf8SJan Medala if (unlikely(rc))
50199ecfbf8SJan Medala return rc;
50299ecfbf8SJan Medala
503f1453604SMichal Krawczyk rc = ena_com_create_and_store_tx_meta_desc(io_sq, ena_tx_ctx, &have_meta);
504f1453604SMichal Krawczyk if (unlikely(rc)) {
505ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
506ac2fd8a5SMichal Krawczyk "Failed to create and store tx meta desc\n");
507b68309beSRafal Kozik return rc;
508b68309beSRafal Kozik }
50999ecfbf8SJan Medala
510b68309beSRafal Kozik /* If the caller doesn't want to send packets */
51199ecfbf8SJan Medala if (unlikely(!num_bufs && !header_len)) {
512b68309beSRafal Kozik rc = ena_com_close_bounce_buffer(io_sq);
5138bf4b06fSShai Brandes if (unlikely(rc))
514ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
515ac2fd8a5SMichal Krawczyk "Failed to write buffers to LLQ\n");
516b68309beSRafal Kozik *nb_hw_desc = io_sq->tail - start_tail;
517b68309beSRafal Kozik return rc;
51899ecfbf8SJan Medala }
51999ecfbf8SJan Medala
52099ecfbf8SJan Medala desc = get_sq_desc(io_sq);
521b68309beSRafal Kozik if (unlikely(!desc))
522b68309beSRafal Kozik return ENA_COM_FAULT;
52399ecfbf8SJan Medala memset(desc, 0x0, sizeof(struct ena_eth_io_tx_desc));
52499ecfbf8SJan Medala
52599ecfbf8SJan Medala /* Set first desc when we don't have meta descriptor */
52699ecfbf8SJan Medala if (!have_meta)
52799ecfbf8SJan Medala desc->len_ctrl |= ENA_ETH_IO_TX_DESC_FIRST_MASK;
52899ecfbf8SJan Medala
529368cbe96SShai Brandes desc->buff_addr_hi_hdr_sz |= ENA_FIELD_PREP((u32)header_len,
530368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_HEADER_LENGTH_MASK,
531368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_HEADER_LENGTH_SHIFT);
532368cbe96SShai Brandes
533368cbe96SShai Brandes desc->len_ctrl |= ENA_FIELD_PREP((u32)io_sq->phase,
534368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_PHASE_MASK,
535368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_PHASE_SHIFT);
53699ecfbf8SJan Medala
53799ecfbf8SJan Medala desc->len_ctrl |= ENA_ETH_IO_TX_DESC_COMP_REQ_MASK;
53899ecfbf8SJan Medala
53999ecfbf8SJan Medala /* Bits 0-9 */
540368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP((u32)ena_tx_ctx->req_id,
541368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_REQ_ID_LO_MASK,
542368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_REQ_ID_LO_SHIFT);
54399ecfbf8SJan Medala
544368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP(ena_tx_ctx->df,
545368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_DF_MASK,
546368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_DF_SHIFT);
54799ecfbf8SJan Medala
54899ecfbf8SJan Medala /* Bits 10-15 */
549368cbe96SShai Brandes desc->len_ctrl |= ENA_FIELD_PREP((ena_tx_ctx->req_id >> 10),
550368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_REQ_ID_HI_MASK,
551368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_REQ_ID_HI_SHIFT);
55299ecfbf8SJan Medala
55399ecfbf8SJan Medala if (ena_tx_ctx->meta_valid) {
554368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP(ena_tx_ctx->tso_enable,
555368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_TSO_EN_MASK,
556368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_TSO_EN_SHIFT);
55799ecfbf8SJan Medala desc->meta_ctrl |= ena_tx_ctx->l3_proto &
55899ecfbf8SJan Medala ENA_ETH_IO_TX_DESC_L3_PROTO_IDX_MASK;
559368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP(ena_tx_ctx->l4_proto,
560368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L4_PROTO_IDX_MASK,
561368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L4_PROTO_IDX_SHIFT);
562368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP(ena_tx_ctx->l3_csum_enable,
563368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L3_CSUM_EN_MASK,
564368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L3_CSUM_EN_SHIFT);
565368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP(ena_tx_ctx->l4_csum_enable,
566368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L4_CSUM_EN_MASK,
567368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L4_CSUM_EN_SHIFT);
568368cbe96SShai Brandes desc->meta_ctrl |= ENA_FIELD_PREP(ena_tx_ctx->l4_csum_partial,
569368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L4_CSUM_PARTIAL_MASK,
570368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_L4_CSUM_PARTIAL_SHIFT);
57199ecfbf8SJan Medala }
57299ecfbf8SJan Medala
57399ecfbf8SJan Medala for (i = 0; i < num_bufs; i++) {
57499ecfbf8SJan Medala /* The first desc share the same desc as the header */
57599ecfbf8SJan Medala if (likely(i != 0)) {
576b68309beSRafal Kozik rc = ena_com_sq_update_tail(io_sq);
57714f3f532SMichal Krawczyk if (unlikely(rc)) {
578ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
579ac2fd8a5SMichal Krawczyk "Failed to update sq tail\n");
580b68309beSRafal Kozik return rc;
58114f3f532SMichal Krawczyk }
58299ecfbf8SJan Medala
58399ecfbf8SJan Medala desc = get_sq_desc(io_sq);
584b68309beSRafal Kozik if (unlikely(!desc))
585b68309beSRafal Kozik return ENA_COM_FAULT;
586b68309beSRafal Kozik
58799ecfbf8SJan Medala memset(desc, 0x0, sizeof(struct ena_eth_io_tx_desc));
58899ecfbf8SJan Medala
589368cbe96SShai Brandes desc->len_ctrl |= ENA_FIELD_PREP((u32)io_sq->phase,
590368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_PHASE_MASK,
591368cbe96SShai Brandes ENA_ETH_IO_TX_DESC_PHASE_SHIFT);
59299ecfbf8SJan Medala }
59399ecfbf8SJan Medala
59499ecfbf8SJan Medala desc->len_ctrl |= ena_bufs->len &
59599ecfbf8SJan Medala ENA_ETH_IO_TX_DESC_LENGTH_MASK;
59699ecfbf8SJan Medala
59799ecfbf8SJan Medala addr_hi = ((ena_bufs->paddr &
59899ecfbf8SJan Medala GENMASK_ULL(io_sq->dma_addr_bits - 1, 32)) >> 32);
59999ecfbf8SJan Medala
60099ecfbf8SJan Medala desc->buff_addr_lo = (u32)ena_bufs->paddr;
60199ecfbf8SJan Medala desc->buff_addr_hi_hdr_sz |= addr_hi &
60299ecfbf8SJan Medala ENA_ETH_IO_TX_DESC_ADDR_HI_MASK;
60399ecfbf8SJan Medala ena_bufs++;
60499ecfbf8SJan Medala }
60599ecfbf8SJan Medala
60699ecfbf8SJan Medala /* set the last desc indicator */
60799ecfbf8SJan Medala desc->len_ctrl |= ENA_ETH_IO_TX_DESC_LAST_MASK;
60899ecfbf8SJan Medala
609b68309beSRafal Kozik rc = ena_com_sq_update_tail(io_sq);
61014f3f532SMichal Krawczyk if (unlikely(rc)) {
611ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_sq_to_ena_dev(io_sq),
612ac2fd8a5SMichal Krawczyk "Failed to update sq tail of the last descriptor\n");
613b68309beSRafal Kozik return rc;
61414f3f532SMichal Krawczyk }
61599ecfbf8SJan Medala
616b68309beSRafal Kozik rc = ena_com_close_bounce_buffer(io_sq);
61799ecfbf8SJan Medala
618b68309beSRafal Kozik *nb_hw_desc = io_sq->tail - start_tail;
619b68309beSRafal Kozik return rc;
62099ecfbf8SJan Medala }
62199ecfbf8SJan Medala
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)62299ecfbf8SJan Medala int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
62399ecfbf8SJan Medala struct ena_com_io_sq *io_sq,
62499ecfbf8SJan Medala struct ena_com_rx_ctx *ena_rx_ctx)
62599ecfbf8SJan Medala {
62699ecfbf8SJan Medala struct ena_com_rx_buf_info *ena_buf = &ena_rx_ctx->ena_bufs[0];
62799ecfbf8SJan Medala struct ena_eth_io_rx_cdesc_base *cdesc = NULL;
62805cffdcfSMichal Krawczyk u16 q_depth = io_cq->q_depth;
62999ecfbf8SJan Medala u16 cdesc_idx = 0;
63099ecfbf8SJan Medala u16 nb_hw_desc;
631b2b02edeSMichal Krawczyk u16 i = 0;
632f73f53f7SShai Brandes int rc;
63399ecfbf8SJan Medala
6343adcba9aSMichal Krawczyk ENA_WARN(io_cq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX,
635ac2fd8a5SMichal Krawczyk ena_com_io_cq_to_ena_dev(io_cq), "wrong Q type");
63699ecfbf8SJan Medala
637f73f53f7SShai Brandes rc = ena_com_cdesc_rx_pkt_get(io_cq, &cdesc_idx, &nb_hw_desc);
638f73f53f7SShai Brandes if (unlikely(rc != ENA_COM_OK))
639f73f53f7SShai Brandes return ENA_COM_FAULT;
640f73f53f7SShai Brandes
6416dcee7cdSJan Medala if (nb_hw_desc == 0) {
64299ecfbf8SJan Medala ena_rx_ctx->descs = nb_hw_desc;
6436dcee7cdSJan Medala return 0;
64499ecfbf8SJan Medala }
64599ecfbf8SJan Medala
646ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
6475c230c36SShai Brandes "Fetch rx packet: queue %u completed desc: %u\n",
64899ecfbf8SJan Medala io_cq->qid, nb_hw_desc);
64999ecfbf8SJan Medala
6506dcee7cdSJan Medala if (unlikely(nb_hw_desc > ena_rx_ctx->max_bufs)) {
651ac2fd8a5SMichal Krawczyk ena_trc_err(ena_com_io_cq_to_ena_dev(io_cq),
6525c230c36SShai Brandes "Too many RX cdescs (%u) > MAX(%u)\n",
65399ecfbf8SJan Medala nb_hw_desc, ena_rx_ctx->max_bufs);
65499ecfbf8SJan Medala return ENA_COM_NO_SPACE;
65599ecfbf8SJan Medala }
65699ecfbf8SJan Medala
657b2b02edeSMichal Krawczyk cdesc = ena_com_rx_cdesc_idx_to_ptr(io_cq, cdesc_idx);
658b2b02edeSMichal Krawczyk ena_rx_ctx->pkt_offset = cdesc->offset;
65999ecfbf8SJan Medala
660b2b02edeSMichal Krawczyk do {
661074262f6SMichal Krawczyk ena_buf[i].len = cdesc->length;
662074262f6SMichal Krawczyk ena_buf[i].req_id = cdesc->req_id;
66305cffdcfSMichal Krawczyk if (unlikely(ena_buf[i].req_id >= q_depth))
66405cffdcfSMichal Krawczyk return ENA_COM_EIO;
665074262f6SMichal Krawczyk
666074262f6SMichal Krawczyk if (++i >= nb_hw_desc)
667074262f6SMichal Krawczyk break;
668074262f6SMichal Krawczyk
669074262f6SMichal Krawczyk cdesc = ena_com_rx_cdesc_idx_to_ptr(io_cq, cdesc_idx + i);
670074262f6SMichal Krawczyk
671074262f6SMichal Krawczyk } while (1);
67299ecfbf8SJan Medala
67399ecfbf8SJan Medala /* Update SQ head ptr */
67499ecfbf8SJan Medala io_sq->next_to_comp += nb_hw_desc;
67599ecfbf8SJan Medala
676ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
6775c230c36SShai Brandes "Updating Queue %u, SQ head to: %u\n",
67899ecfbf8SJan Medala io_sq->qid, io_sq->next_to_comp);
67999ecfbf8SJan Medala
68099ecfbf8SJan Medala /* Get rx flags from the last pkt */
681eea9fc6aSShai Brandes ena_com_rx_set_flags(ena_rx_ctx, cdesc);
682eea9fc6aSShai Brandes
683eea9fc6aSShai Brandes ena_trc_dbg(ena_com_io_cq_to_ena_dev(io_cq),
684eea9fc6aSShai Brandes "l3_proto %d l4_proto %d l3_csum_err %d l4_csum_err %d hash %d frag %d cdesc_status %x\n",
685eea9fc6aSShai Brandes ena_rx_ctx->l3_proto,
686eea9fc6aSShai Brandes ena_rx_ctx->l4_proto,
687eea9fc6aSShai Brandes ena_rx_ctx->l3_csum_err,
688eea9fc6aSShai Brandes ena_rx_ctx->l4_csum_err,
689eea9fc6aSShai Brandes ena_rx_ctx->hash,
690eea9fc6aSShai Brandes ena_rx_ctx->frag,
691eea9fc6aSShai Brandes cdesc->status);
69299ecfbf8SJan Medala
69399ecfbf8SJan Medala ena_rx_ctx->descs = nb_hw_desc;
694ac2fd8a5SMichal Krawczyk
69599ecfbf8SJan Medala return 0;
69699ecfbf8SJan Medala }
69799ecfbf8SJan Medala
ena_com_add_single_rx_desc(struct ena_com_io_sq * io_sq,struct ena_com_buf * ena_buf,u16 req_id)69899ecfbf8SJan Medala int ena_com_add_single_rx_desc(struct ena_com_io_sq *io_sq,
69999ecfbf8SJan Medala struct ena_com_buf *ena_buf,
70099ecfbf8SJan Medala u16 req_id)
70199ecfbf8SJan Medala {
70299ecfbf8SJan Medala struct ena_eth_io_rx_desc *desc;
70399ecfbf8SJan Medala
7043adcba9aSMichal Krawczyk ENA_WARN(io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX,
705ac2fd8a5SMichal Krawczyk ena_com_io_sq_to_ena_dev(io_sq), "wrong Q type");
70699ecfbf8SJan Medala
707b68309beSRafal Kozik if (unlikely(!ena_com_sq_have_enough_space(io_sq, 1)))
7086dcee7cdSJan Medala return ENA_COM_NO_SPACE;
70999ecfbf8SJan Medala
710d8c48317SShai Brandes /* virt_addr allocation success is checked before calling this function */
711d8c48317SShai Brandes desc = get_sq_desc_regular_queue(io_sq);
712b68309beSRafal Kozik
71399ecfbf8SJan Medala memset(desc, 0x0, sizeof(struct ena_eth_io_rx_desc));
71499ecfbf8SJan Medala
71599ecfbf8SJan Medala desc->length = ena_buf->len;
71699ecfbf8SJan Medala
717b2b02edeSMichal Krawczyk desc->ctrl = ENA_ETH_IO_RX_DESC_FIRST_MASK |
718b2b02edeSMichal Krawczyk ENA_ETH_IO_RX_DESC_LAST_MASK |
719b19f366cSMichal Krawczyk ENA_ETH_IO_RX_DESC_COMP_REQ_MASK |
720368cbe96SShai Brandes ENA_FIELD_GET(io_sq->phase,
721368cbe96SShai Brandes ENA_ETH_IO_RX_DESC_PHASE_MASK,
722368cbe96SShai Brandes ENA_ZERO_SHIFT);
72399ecfbf8SJan Medala
72499ecfbf8SJan Medala desc->req_id = req_id;
72599ecfbf8SJan Medala
726ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_com_io_sq_to_ena_dev(io_sq),
7275c230c36SShai Brandes "Adding single RX desc, Queue: %u, req_id: %u\n",
7285c230c36SShai Brandes io_sq->qid, req_id);
729ac2fd8a5SMichal Krawczyk
73099ecfbf8SJan Medala desc->buff_addr_lo = (u32)ena_buf->paddr;
73199ecfbf8SJan Medala desc->buff_addr_hi =
7323adcba9aSMichal Krawczyk ((ena_buf->paddr & GENMASK_ULL(io_sq->dma_addr_bits - 1, 32)) >> 32);
73399ecfbf8SJan Medala
7348a344a55SShai Brandes return ena_com_sq_update_reqular_queue_tail(io_sq);
73599ecfbf8SJan Medala }
7363adcba9aSMichal Krawczyk
ena_com_cq_empty(struct ena_com_io_cq * io_cq)7373adcba9aSMichal Krawczyk bool ena_com_cq_empty(struct ena_com_io_cq *io_cq)
7383adcba9aSMichal Krawczyk {
7393adcba9aSMichal Krawczyk struct ena_eth_io_rx_cdesc_base *cdesc;
7403adcba9aSMichal Krawczyk
7413adcba9aSMichal Krawczyk cdesc = ena_com_get_next_rx_cdesc(io_cq);
7423adcba9aSMichal Krawczyk if (cdesc)
7433adcba9aSMichal Krawczyk return false;
7443adcba9aSMichal Krawczyk else
7453adcba9aSMichal Krawczyk return true;
7463adcba9aSMichal Krawczyk }
747