xref: /dpdk/drivers/net/ena/base/ena_eth_com.c (revision 95eaa71c66eadb6a6924cc5241e02d3dcc58217c)
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