Skip to contentSkip to conversation

net/ena: ENAv2 release

PATCH In review Michal Krawczyk 2 participants 24 messages Dec 14, 2018 – Dec 18, 2018 Network drivers

lore
Share & tools
lore
#0 lore raw

cover net/ena: ENAv2 release

Hi,

we are proud to announce ENAv2 driver for the DPDK.
It is already available for the Linux, and now also ENAv2 can be used with DPDK on the appropriate AWS instances.

To summarize, this release contains:

**New major features**
* LLQv2 which is Low Latency Queue v2. This feature reduces the latency of the packets by pushing the header directly through the PCI to the device, before the DMA is even triggered. This allows the NIC to asynchronously prepare for the next incoming packet, when the DMA will be finished.
* Independent configuration of HW Tx and Rx ring depths. Also, on some instances it is possible to create 8k Rx descriptors per ring.
* Additional doorbell check on Tx, to handle Tx more efficiently for big bursts of packets
* Per queue statistics
* Extended statistics using xstats DPDK API

**New major bug fixes**
* The reset routine was aligned with the DPDK API, so now it can be handled as in other PMDs
* Fixes for OOO completion
* Fixes for memory leaks due to port stops and starts in the middle of traffic

There are also minor bug fixes and features in addition to the ones mentioned above.

Michal Krawczyk (4):
net/ena: add LLQv2 support
net/ena: add per-queue software counters stats
docs: update ENA PMD documentation and features
net/ena: release of the ENAv2 driver (v2.0.0)

Rafal Kozik (15):
net/ena: update ena_com for the ENAv2
net/ena: pass number of CPUs to the host info structure net/ena: add reset reason in rx error
net/ena: add hw queues depth setup
net/ena: skip packet with wrong req_id net/ena: increase maximum Rx ring size net/ena: call additional doorbells if needed net/ena: destroy queues if start failed net/ena: reset should not reconfigure queues net/ena: adjust new line in log messages net/ena: add supported RSS offloads types net/ena: fix invalid reference to variable in union net/ena: fix cleanup for out of order packets net/ena: new way of getting rx drops
net/ena: update completion queue after cleanup

Solganik Alexander (1):
net/ena: expose ENA-specific statistics in extended stats

 doc/guides/nics/ena.rst                         |  31 +-
 doc/guides/nics/features/ena.ini                |  12 +-
 drivers/net/ena/base/ena_com.c                  | 479 ++++++++++---
 drivers/net/ena/base/ena_com.h                  | 111 ++-
 drivers/net/ena/base/ena_defs/ena_admin_defs.h  | 567 ++++++++++-----
 drivers/net/ena/base/ena_defs/ena_common_defs.h |   5 +-
 drivers/net/ena/base/ena_defs/ena_eth_io_defs.h | 244 +++----
 drivers/net/ena/base/ena_defs/ena_gen_info.h    |   5 +-
 drivers/net/ena/base/ena_defs/ena_includes.h    |  33 -
 drivers/net/ena/base/ena_defs/ena_regs_defs.h   | 207 +++---
 drivers/net/ena/base/ena_eth_com.c              | 334 ++++++---
 drivers/net/ena/base/ena_eth_com.h              |  87 ++-
 drivers/net/ena/base/ena_plat.h                 |  12 +-
 drivers/net/ena/base/ena_plat_dpdk.h            |  35 +-
 drivers/net/ena/ena_ethdev.c                    | 902 +++++++++++++++++-------
 drivers/net/ena/ena_ethdev.h                    |  79 ++-
 16 files changed, 2174 insertions(+), 969 deletions(-)

--
2.14.1

#1 lore raw

PATCH 1/20 net/ena: update ena_com for the ENAv2

From: Rafal Kozik <[email protected]>

ena_com is the communication layer provided by the vendor and common to all ENA drivers.
This patch updates it to version from 2018.09.26.

It adds support for ENAv2 device together with LLQ feature, adds doorbell optimization and reconfiguration of HW queues depth independently.

The driver was adjusted to the new changes in the HAL.

---
 drivers/net/ena/base/ena_com.c                  | 479 ++++++++++++++++----
 drivers/net/ena/base/ena_com.h                  | 111 ++++-
 drivers/net/ena/base/ena_defs/ena_admin_defs.h  | 567 ++++++++++++++++--------
 drivers/net/ena/base/ena_defs/ena_common_defs.h |   5 +-
 drivers/net/ena/base/ena_defs/ena_eth_io_defs.h | 244 +++++-----
 drivers/net/ena/base/ena_defs/ena_gen_info.h    |   5 +-
 drivers/net/ena/base/ena_defs/ena_includes.h    |  33 --
 drivers/net/ena/base/ena_defs/ena_regs_defs.h   | 207 ++++-----
 drivers/net/ena/base/ena_eth_com.c              | 334 +++++++++-----
 drivers/net/ena/base/ena_eth_com.h              |  87 +++-
 drivers/net/ena/base/ena_plat.h                 |  12 +-
 drivers/net/ena/base/ena_plat_dpdk.h            |  35 +-
 drivers/net/ena/ena_ethdev.c                    |   4 +-
 13 files changed, 1462 insertions(+), 661 deletions(-)
drivers/net/ena/base/ena_com.c +400 -79
index 4abf1a28a..b688067f7 100644
@@ -42,17 +42,6 @@
 #define ENA_ASYNC_QUEUE_DEPTH 16
 #define ENA_ADMIN_QUEUE_DEPTH 32
 
-#ifdef ENA_EXTENDED_STATS
-
-#define ENA_HISTOGRAM_ACTIVE_MASK_OFFSET 0xF08
-#define ENA_EXTENDED_STAT_GET_FUNCT(_funct_queue) (_funct_queue & 0xFFFF)
-#define ENA_EXTENDED_STAT_GET_QUEUE(_funct_queue) (_funct_queue >> 16)
-
-#endif /* ENA_EXTENDED_STATS */
-
-#define MIN_ENA_VER (((ENA_COMMON_SPEC_VERSION_MAJOR) << \
-		ENA_REGS_VERSION_MAJOR_VERSION_SHIFT) \
-		| (ENA_COMMON_SPEC_VERSION_MINOR))
 
 #define ENA_CTRL_MAJOR		0
 #define ENA_CTRL_MINOR		0
@@ -70,6 +59,8 @@
 
 #define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF
 
+#define ENA_COM_BOUNCE_BUFFER_CNTRL_CNT	4
+
 #define ENA_REGS_ADMIN_INTR_MASK 1
 
 #define ENA_POLL_MS	5
@@ -247,7 +238,7 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu
 	tail_masked = admin_queue->sq.tail & queue_size_mask;
 
 	/* In case of queue FULL */
-	cnt = ATOMIC32_READ(&admin_queue->outstanding_cmds);
+	cnt = (u16)ATOMIC32_READ(&admin_queue->outstanding_cmds);
 	if (cnt >= admin_queue->q_depth) {
 		ena_trc_dbg("admin queue is full.\n");
 		admin_queue->stats.out_of_space++;
@@ -284,6 +275,7 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu
 	if (unlikely((admin_queue->sq.tail & queue_size_mask) == 0))
 		admin_queue->sq.phase = !admin_queue->sq.phase;
 
+	ENA_DB_SYNC(&admin_queue->sq.mem_handle);
 	ENA_REG_WRITE32(admin_queue->bus, admin_queue->sq.tail,
 			admin_queue->sq.db_addr);
 
@@ -345,12 +337,14 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
 
 	memset(&io_sq->desc_addr, 0x0, sizeof(io_sq->desc_addr));
 
+	io_sq->dma_addr_bits = (u8)ena_dev->dma_addr_bits;
 	io_sq->desc_entry_size =
 		(io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ?
 		sizeof(struct ena_eth_io_tx_desc) :
 		sizeof(struct ena_eth_io_rx_desc);
 
 	size = io_sq->desc_entry_size * io_sq->q_depth;
+	io_sq->bus = ena_dev->bus;
 
 	if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) {
 		ENA_MEM_ALLOC_COHERENT_NODE(ena_dev->dmadev,
@@ -367,21 +361,47 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
 					       io_sq->desc_addr.phys_addr,
 					       io_sq->desc_addr.mem_handle);
 		}
-	} else {
+
+		if (!io_sq->desc_addr.virt_addr) {
+			ena_trc_err("memory allocation failed");
+			return ENA_COM_NO_MEM;
+		}
+	}
+
+	if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
+		/* Allocate bounce buffers */
+		io_sq->bounce_buf_ctrl.buffer_size = ena_dev->llq_info.desc_list_entry_size;
+		io_sq->bounce_buf_ctrl.buffers_num = ENA_COM_BOUNCE_BUFFER_CNTRL_CNT;
+		io_sq->bounce_buf_ctrl.next_to_use = 0;
+
+		size = io_sq->bounce_buf_ctrl.buffer_size * io_sq->bounce_buf_ctrl.buffers_num;
+
 		ENA_MEM_ALLOC_NODE(ena_dev->dmadev,
 				   size,
-				   io_sq->desc_addr.virt_addr,
+				   io_sq->bounce_buf_ctrl.base_buffer,
 				   ctx->numa_node,
 				   dev_node);
-		if (!io_sq->desc_addr.virt_addr) {
-			io_sq->desc_addr.virt_addr =
-				ENA_MEM_ALLOC(ena_dev->dmadev, size);
+		if (!io_sq->bounce_buf_ctrl.base_buffer)
+			io_sq->bounce_buf_ctrl.base_buffer = ENA_MEM_ALLOC(ena_dev->dmadev, size);
+
+		if (!io_sq->bounce_buf_ctrl.base_buffer) {
+			ena_trc_err("bounce buffer memory allocation failed");
+			return ENA_COM_NO_MEM;
 		}
-	}
 
-	if (!io_sq->desc_addr.virt_addr) {
-		ena_trc_err("memory allocation failed");
-		return ENA_COM_NO_MEM;
+		memcpy(&io_sq->llq_info, &ena_dev->llq_info, sizeof(io_sq->llq_info));
+
+		/* Initiate the first bounce buffer */
+		io_sq->llq_buf_ctrl.curr_bounce_buf =
+			ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl);
+		memset(io_sq->llq_buf_ctrl.curr_bounce_buf,
+		       0x0, io_sq->llq_info.desc_list_entry_size);
+		io_sq->llq_buf_ctrl.descs_left_in_line =
+			io_sq->llq_info.descs_num_before_header;
+
+		if (io_sq->llq_info.max_entries_in_tx_burst > 0)
+			io_sq->entries_in_tx_burst_left =
+				io_sq->llq_info.max_entries_in_tx_burst;
 	}
 
 	io_sq->tail = 0;
@@ -407,6 +427,7 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev,
 		sizeof(struct ena_eth_io_rx_cdesc_base);
 
 	size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth;
+	io_cq->bus = ena_dev->bus;
 
 	ENA_MEM_ALLOC_COHERENT_NODE(ena_dev->dmadev,
 			size,
@@ -473,12 +494,12 @@ static void ena_com_handle_admin_completion(struct ena_com_admin_queue *admin_qu
 	cqe = &admin_queue->cq.entries[head_masked];
 
 	/* Go over all the completions */
-	while ((cqe->acq_common_descriptor.flags &
+	while ((READ_ONCE8(cqe->acq_common_descriptor.flags) &
 			ENA_ADMIN_ACQ_COMMON_DESC_PHASE_MASK) == phase) {
 		/* Do not read the rest of the completion entry before the
 		 * phase bit was validated
 		 */
-		rmb();
+		dma_rmb();
 		ena_com_handle_single_admin_completion(admin_queue, cqe);
 
 		head_masked++;
@@ -572,6 +593,168 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c
 	return ret;
 }
 
+/**
+ * Set the LLQ configurations of the firmware
+ *
+ * The driver provides only the enabled feature values to the FW,
+ * which in turn, checks if they are supported.
+ */
+static int ena_com_set_llq(struct ena_com_dev *ena_dev)
+{
+	struct ena_com_admin_queue *admin_queue;
+	struct ena_admin_set_feat_cmd cmd;
+	struct ena_admin_set_feat_resp resp;
+	struct ena_com_llq_info *llq_info = &ena_dev->llq_info;
+	int ret;
+
+	memset(&cmd, 0x0, sizeof(cmd));
+	admin_queue = &ena_dev->admin_queue;
+
+	cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE;
+	cmd.feat_common.feature_id = ENA_ADMIN_LLQ;
+
+	cmd.u.llq.header_location_ctrl_enabled = llq_info->header_location_ctrl;
+	cmd.u.llq.entry_size_ctrl_enabled = llq_info->desc_list_entry_size_ctrl;
+	cmd.u.llq.desc_num_before_header_enabled = llq_info->descs_num_before_header;
+	cmd.u.llq.descriptors_stride_ctrl_enabled = llq_info->desc_stride_ctrl;
+
+	ret = ena_com_execute_admin_command(admin_queue,
+					    (struct ena_admin_aq_entry *)&cmd,
+					    sizeof(cmd),
+					    (struct ena_admin_acq_entry *)&resp,
+					    sizeof(resp));
+
+	if (unlikely(ret))
+		ena_trc_err("Failed to set LLQ configurations: %d\n", ret);
+
+	return ret;
+}
+
+static int ena_com_config_llq_info(struct ena_com_dev *ena_dev,
+				   struct ena_admin_feature_llq_desc *llq_features,
+				   struct ena_llq_configurations *llq_default_cfg)
+{
+	struct ena_com_llq_info *llq_info = &ena_dev->llq_info;
+	u16 supported_feat;
+	int rc;
+
+	memset(llq_info, 0, sizeof(*llq_info));
+
+	supported_feat = llq_features->header_location_ctrl_supported;
+
+	if (likely(supported_feat & llq_default_cfg->llq_header_location)) {
+		llq_info->header_location_ctrl = llq_default_cfg->llq_header_location;
+	} else {
+		ena_trc_err("Invalid header location control, supported: 0x%x\n",
+			    supported_feat);
+		return -EINVAL;
+	}
+
+	if (likely(llq_info->header_location_ctrl == ENA_ADMIN_INLINE_HEADER)) {
+		llq_info->inline_header = true;
+
+		supported_feat = llq_features->descriptors_stride_ctrl_supported;
+		if (likely(supported_feat & llq_default_cfg->llq_stride_ctrl)) {
+			llq_info->desc_stride_ctrl = llq_default_cfg->llq_stride_ctrl;
+		} else	{
+			if (supported_feat & ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY) {
+				llq_info->desc_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY;
+			} else if (supported_feat & ENA_ADMIN_SINGLE_DESC_PER_ENTRY) {
+				llq_info->desc_stride_ctrl = ENA_ADMIN_SINGLE_DESC_PER_ENTRY;
+			} else {
+				ena_trc_err("Invalid desc_stride_ctrl, supported: 0x%x\n",
+					    supported_feat);
+				return -EINVAL;
+			}
+
+			ena_trc_err("Default llq stride ctrl is not supported, performing fallback,"
+				    "default: 0x%x, supported: 0x%x, used: 0x%x\n",
+				    llq_default_cfg->llq_stride_ctrl,
+				    supported_feat,
+				    llq_info->desc_stride_ctrl);
+		}
+	} else {
+		llq_info->inline_header = false;
+		llq_info->desc_stride_ctrl = 0;
+	}
+
+	supported_feat = llq_features->entry_size_ctrl_supported;
+	if (likely(supported_feat & llq_default_cfg->llq_ring_entry_size)) {
+		llq_info->desc_list_entry_size_ctrl = llq_default_cfg->llq_ring_entry_size;
+		llq_info->desc_list_entry_size = llq_default_cfg->llq_ring_entry_size_value;
+	} else {
+		if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_128B) {
+			llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_128B;
+			llq_info->desc_list_entry_size = 128;
+		} else if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_192B) {
+			llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_192B;
+			llq_info->desc_list_entry_size = 192;
+		} else if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_256B) {
+			llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_256B;
+			llq_info->desc_list_entry_size = 256;
+		} else {
+			ena_trc_err("Invalid entry_size_ctrl, supported: 0x%x\n", supported_feat);
+			return -EINVAL;
+		}
+
+		ena_trc_err("Default llq ring entry size is not supported, performing fallback,"
+			    "default: 0x%x, supported: 0x%x, used: 0x%x\n",
+			    llq_default_cfg->llq_ring_entry_size,
+			    supported_feat,
+			    llq_info->desc_list_entry_size);
+	}
+	if (unlikely(llq_info->desc_list_entry_size & 0x7)) {
+		/* The desc list entry size should be whole multiply of 8
+		 * This requirement comes from __iowrite64_copy()
+		 */
+		ena_trc_err("illegal entry size %d\n",
+			    llq_info->desc_list_entry_size);
+		return -EINVAL;
+	}
+
+	if (llq_info->desc_stride_ctrl == ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY)
+		llq_info->descs_per_entry = llq_info->desc_list_entry_size /
+			sizeof(struct ena_eth_io_tx_desc);
+	else
+		llq_info->descs_per_entry = 1;
+
+	supported_feat = llq_features->desc_num_before_header_supported;
+	if (likely(supported_feat & llq_default_cfg->llq_num_decs_before_header)) {
+		llq_info->descs_num_before_header = llq_default_cfg->llq_num_decs_before_header;
+	} else {
+		if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2) {
+			llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2;
+		} else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_1) {
+			llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_1;
+		} else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_4) {
+			llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_4;
+		} else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_8) {
+			llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_8;
+		} else {
+			ena_trc_err("Invalid descs_num_before_header, supported: 0x%x\n",
+				    supported_feat);
+			return -EINVAL;
+		}
+
+		ena_trc_err("Default llq num descs before header is not supported, performing fallback,"
+			    "default: 0x%x, supported: 0x%x, used: 0x%x\n",
+			    llq_default_cfg->llq_num_decs_before_header,
+			    supported_feat,
+			    llq_info->descs_num_before_header);
+	}
+
+	llq_info->max_entries_in_tx_burst =
+		(u16)(llq_features->max_tx_burst_size /	llq_default_cfg->llq_ring_entry_size_value);
+
+	rc = ena_com_set_llq(ena_dev);
+	if (rc)
+		ena_trc_err("Cannot set LLQ configuration: %d\n", rc);
+
+	return 0;
+}
+
+
+
 static int ena_com_wait_and_process_admin_cq_interrupts(struct ena_comp_ctx *comp_ctx,
 							struct ena_com_admin_queue *admin_queue)
 {
@@ -641,15 +824,11 @@ static u32 ena_com_reg_bar_read32(struct ena_com_dev *ena_dev, u16 offset)
 	mmio_read_reg |= mmio_read->seq_num &
 			ENA_REGS_MMIO_REG_READ_REQ_ID_MASK;
 
-	/* make sure read_resp->req_id get updated before the hw can write
-	 * there
-	 */
-	wmb();
-
-	ENA_REG_WRITE32(ena_dev->bus, mmio_read_reg, ena_dev->reg_bar + ENA_REGS_MMIO_REG_READ_OFF);
+	ENA_REG_WRITE32(ena_dev->bus, mmio_read_reg,
+			ena_dev->reg_bar + ENA_REGS_MMIO_REG_READ_OFF);
 
 	for (i = 0; i < timeout; i++) {
-		if (read_resp->req_id == mmio_read->seq_num)
+		if (READ_ONCE16(read_resp->req_id) == mmio_read->seq_num)
 			break;
 
 		ENA_UDELAY(1);
@@ -751,17 +930,20 @@ static void ena_com_io_queue_free(struct ena_com_dev *ena_dev,
 	if (io_sq->desc_addr.virt_addr) {
 		size = io_sq->desc_entry_size * io_sq->q_depth;
 
-		if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
-			ENA_MEM_FREE_COHERENT(ena_dev->dmadev,
-					      size,
-					      io_sq->desc_addr.virt_addr,
-					      io_sq->desc_addr.phys_addr,
-					      io_sq->desc_addr.mem_handle);
-		else
-			ENA_MEM_FREE(ena_dev->dmadev, io_sq->desc_addr.virt_addr);
+		ENA_MEM_FREE_COHERENT(ena_dev->dmadev,
+				      size,
+				      io_sq->desc_addr.virt_addr,
+				      io_sq->desc_addr.phys_addr,
+				      io_sq->desc_addr.mem_handle);
 
 		io_sq->desc_addr.virt_addr = NULL;
 	}
+
+	if (io_sq->bounce_buf_ctrl.base_buffer) {
+		size = io_sq->llq_info.desc_list_entry_size * ENA_COM_BOUNCE_BUFFER_CNTRL_CNT;
+		ENA_MEM_FREE(ena_dev->dmadev, io_sq->bounce_buf_ctrl.base_buffer);
+		io_sq->bounce_buf_ctrl.base_buffer = NULL;
+	}
 }
 
 static int wait_for_reset_state(struct ena_com_dev *ena_dev, u32 timeout,
@@ -807,7 +989,8 @@ static int ena_com_get_feature_ex(struct ena_com_dev *ena_dev,
 				  struct ena_admin_get_feat_resp *get_resp,
 				  enum ena_admin_aq_feature_id feature_id,
 				  dma_addr_t control_buf_dma_addr,
-				  u32 control_buff_size)
+				  u32 control_buff_size,
+				  u8 feature_ver)
 {
 	struct ena_com_admin_queue *admin_queue;
 	struct ena_admin_get_feat_cmd get_cmd;
@@ -838,7 +1021,7 @@ static int ena_com_get_feature_ex(struct ena_com_dev *ena_dev,
 	}
 
 	get_cmd.control_buffer.length = control_buff_size;
-
+	get_cmd.feat_common.feature_version = feature_ver;
 	get_cmd.feat_common.feature_id = feature_id;
 
 	ret = ena_com_execute_admin_command(admin_queue,
@@ -858,13 +1041,15 @@ static int ena_com_get_feature_ex(struct ena_com_dev *ena_dev,
 
 static int ena_com_get_feature(struct ena_com_dev *ena_dev,
 			       struct ena_admin_get_feat_resp *get_resp,
-			       enum ena_admin_aq_feature_id feature_id)
+			       enum ena_admin_aq_feature_id feature_id,
+			       u8 feature_ver)
 {
 	return ena_com_get_feature_ex(ena_dev,
 				      get_resp,
 				      feature_id,
 				      0,
-				      0);
+				      0,
+				      feature_ver);
 }
 
 static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev)
@@ -934,7 +1119,7 @@ static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev,
 	int ret;
 
 	ret = ena_com_get_feature(ena_dev, &get_resp,
-				  ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG);
+				  ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG, 0);
 	if (unlikely(ret))
 		return ret;
 
@@ -1364,14 +1549,14 @@ int ena_com_set_aenq_config(struct ena_com_dev *ena_dev, u32 groups_flag)
 	struct ena_admin_get_feat_resp get_resp;
 	int ret;
 
-	ret = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_AENQ_CONFIG);
+	ret = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_AENQ_CONFIG, 0);
 	if (ret) {
 		ena_trc_info("Can't get aenq configuration\n");
 		return ret;
 	}
 
 	if ((get_resp.u.aenq.supported_groups & groups_flag) != groups_flag) {
-		ena_trc_warn("Trying to set unsupported aenq events. supported flag: %x asked flag: %x\n",
+		ena_trc_warn("Trying to set unsupported aenq events. supported flag: 0x%x asked flag: 0x%x\n",
 			     get_resp.u.aenq.supported_groups,
 			     groups_flag);
 		return ENA_COM_UNSUPPORTED;
@@ -1446,11 +1631,6 @@ int ena_com_validate_version(struct ena_com_dev *ena_dev)
 		     ENA_REGS_VERSION_MAJOR_VERSION_SHIFT,
 		     ver & ENA_REGS_VERSION_MINOR_VERSION_MASK);
 
-	if (ver < MIN_ENA_VER) {
-		ena_trc_err("ENA version is lower than the minimal version the driver supports\n");
-		return -1;
-	}
-
 	ena_trc_info("ena controller version: %d.%d.%d implementation version %d\n",
 		     (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_MASK)
 		     >> ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_SHIFT,
@@ -1503,6 +1683,7 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev)
 		ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, aenq->entries,
 				      aenq->dma_addr, aenq->mem_handle);
 	aenq->entries = NULL;
+	ENA_SPINLOCK_DESTROY(admin_queue->q_lock);
 }
 
 void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)
@@ -1512,7 +1693,8 @@ void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)
 	if (polling)
 		mask_value = ENA_REGS_ADMIN_INTR_MASK;
 
-	ENA_REG_WRITE32(ena_dev->bus, mask_value, ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF);
+	ENA_REG_WRITE32(ena_dev->bus, mask_value,
+			ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF);
 	ena_dev->admin_queue.polling = polling;
 }
 
@@ -1527,7 +1709,7 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev)
 			       mmio_read->read_resp_dma_addr,
 			       mmio_read->read_resp_mem_handle);
 	if (unlikely(!mmio_read->read_resp))
-		return ENA_COM_NO_MEM;
+		goto err;
 
 	ena_com_mmio_reg_read_request_write_dev_addr(ena_dev);
 
@@ -1536,6 +1718,10 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev)
 	mmio_read->readless_supported = true;
 
 	return 0;
+
+err:
+		ENA_SPINLOCK_DESTROY(mmio_read->lock);
+		return ENA_COM_NO_MEM;
 }
 
 void ena_com_set_mmio_read_mode(struct ena_com_dev *ena_dev, bool readless_supported)
@@ -1559,6 +1745,7 @@ void ena_com_mmio_reg_read_request_destroy(struct ena_com_dev *ena_dev)
 			      mmio_read->read_resp_mem_handle);
 
 	mmio_read->read_resp = NULL;
+	ENA_SPINLOCK_DESTROY(mmio_read->lock);
 }
 
 void ena_com_mmio_reg_read_request_write_dev_addr(struct ena_com_dev *ena_dev)
@@ -1574,8 +1761,7 @@ void ena_com_mmio_reg_read_request_write_dev_addr(struct ena_com_dev *ena_dev)
 }
 
 int ena_com_admin_init(struct ena_com_dev *ena_dev,
-		       struct ena_aenq_handlers *aenq_handlers,
-		       bool init_spinlock)
+		       struct ena_aenq_handlers *aenq_handlers)
 {
 	struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue;
 	u32 aq_caps, acq_caps, dev_sts, addr_low, addr_high;
@@ -1595,14 +1781,14 @@ int ena_com_admin_init(struct ena_com_dev *ena_dev,
 
 	admin_queue->q_depth = ENA_ADMIN_QUEUE_DEPTH;
 
+	admin_queue->bus = ena_dev->bus;
 	admin_queue->q_dmadev = ena_dev->dmadev;
 	admin_queue->polling = false;
 	admin_queue->curr_cmd_id = 0;
 
 	ATOMIC32_SET(&admin_queue->outstanding_cmds, 0);
 
-	if (init_spinlock)
-		ENA_SPINLOCK_INIT(admin_queue->q_lock);
+	ENA_SPINLOCK_INIT(admin_queue->q_lock);
 
 	ret = ena_com_init_comp_ctxt(admin_queue);
 	if (ret)
@@ -1742,7 +1928,63 @@ void ena_com_destroy_io_queue(struct ena_com_dev *ena_dev, u16 qid)
 int ena_com_get_link_params(struct ena_com_dev *ena_dev,
 			    struct ena_admin_get_feat_resp *resp)
 {
-	return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG);
+	return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG, 0);
+}
+
+int ena_com_extra_properties_strings_init(struct ena_com_dev *ena_dev)
+{
+	struct ena_admin_get_feat_resp resp;
+	struct ena_extra_properties_strings *extra_properties_strings =
+			&ena_dev->extra_properties_strings;
+	u32 rc;
+	extra_properties_strings->size = ENA_ADMIN_EXTRA_PROPERTIES_COUNT *
+		ENA_ADMIN_EXTRA_PROPERTIES_STRING_LEN;
+
+	ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev,
+			       extra_properties_strings->size,
+			       extra_properties_strings->virt_addr,
+			       extra_properties_strings->dma_addr,
+			       extra_properties_strings->dma_handle);
+	if (unlikely(!extra_properties_strings->virt_addr)) {
+		ena_trc_err("Failed to allocate extra properties strings\n");
+		return 0;
+	}
+
+	rc = ena_com_get_feature_ex(ena_dev, &resp,
+				    ENA_ADMIN_EXTRA_PROPERTIES_STRINGS,
+				    extra_properties_strings->dma_addr,
+				    extra_properties_strings->size, 0);
+	if (rc) {
+		ena_trc_dbg("Failed to get extra properties strings\n");
+		goto err;
+	}
+
+	return resp.u.extra_properties_strings.count;
+err:
+	ena_com_delete_extra_properties_strings(ena_dev);
+	return 0;
+}
+
+void ena_com_delete_extra_properties_strings(struct ena_com_dev *ena_dev)
+{
+	struct ena_extra_properties_strings *extra_properties_strings =
+				&ena_dev->extra_properties_strings;
+
+	if (extra_properties_strings->virt_addr) {
+		ENA_MEM_FREE_COHERENT(ena_dev->dmadev,
+				      extra_properties_strings->size,
+				      extra_properties_strings->virt_addr,
+				      extra_properties_strings->dma_addr,
+				      extra_properties_strings->dma_handle);
+		extra_properties_strings->virt_addr = NULL;
+	}
+}
+
+int ena_com_get_extra_properties_flags(struct ena_com_dev *ena_dev,
+				       struct ena_admin_get_feat_resp *resp)
+{
+	return ena_com_get_feature(ena_dev, resp,
+				   ENA_ADMIN_EXTRA_PROPERTIES_FLAGS, 0);
 }
 
 int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
@@ -1752,7 +1994,7 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
 	int rc;
 
 	rc = ena_com_get_feature(ena_dev, &get_resp,
-				 ENA_ADMIN_DEVICE_ATTRIBUTES);
+				 ENA_ADMIN_DEVICE_ATTRIBUTES, 0);
 	if (rc)
 		return rc;
 
@@ -1760,17 +2002,34 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
 	       sizeof(get_resp.u.dev_attr));
 	ena_dev->supported_features = get_resp.u.dev_attr.supported_features;
 
-	rc = ena_com_get_feature(ena_dev, &get_resp,
-				 ENA_ADMIN_MAX_QUEUES_NUM);
-	if (rc)
-		return rc;
+	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
+		rc = ena_com_get_feature(ena_dev, &get_resp,
+					 ENA_ADMIN_MAX_QUEUES_EXT,
+					 ENA_FEATURE_MAX_QUEUE_EXT_VER);
+		if (rc)
+			return rc;
+
+		if (get_resp.u.max_queue_ext.version != ENA_FEATURE_MAX_QUEUE_EXT_VER)
+			return -EINVAL;
+
+		memcpy(&get_feat_ctx->max_queue_ext, &get_resp.u.max_queue_ext,
+		       sizeof(get_resp.u.max_queue_ext));
+		ena_dev->tx_max_header_size =
+			get_resp.u.max_queue_ext.max_queue_ext.max_tx_header_size;
+	} else {
+		rc = ena_com_get_feature(ena_dev, &get_resp,
+					 ENA_ADMIN_MAX_QUEUES_NUM, 0);
+		memcpy(&get_feat_ctx->max_queues, &get_resp.u.max_queue,
+		       sizeof(get_resp.u.max_queue));
+		ena_dev->tx_max_header_size =
+			get_resp.u.max_queue.max_header_size;
 
-	memcpy(&get_feat_ctx->max_queues, &get_resp.u.max_queue,
-	       sizeof(get_resp.u.max_queue));
-	ena_dev->tx_max_header_size = get_resp.u.max_queue.max_header_size;
+		if (rc)
+			return rc;
+	}
 
 	rc = ena_com_get_feature(ena_dev, &get_resp,
-				 ENA_ADMIN_AENQ_CONFIG);
+				 ENA_ADMIN_AENQ_CONFIG, 0);
 	if (rc)
 		return rc;
 
@@ -1778,7 +2037,7 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
 	       sizeof(get_resp.u.aenq));
 
 	rc = ena_com_get_feature(ena_dev, &get_resp,
-				 ENA_ADMIN_STATELESS_OFFLOAD_CONFIG);
+				 ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0);
 	if (rc)
 		return rc;
 
@@ -1788,7 +2047,7 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
 	/* Driver hints isn't mandatory admin command. So in case the
 	 * command isn't supported set driver hints to 0
 	 */
-	rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_HW_HINTS);
+	rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_HW_HINTS, 0);
 
 	if (!rc)
 		memcpy(&get_feat_ctx->hw_hints, &get_resp.u.hw_hints,
@@ -1798,6 +2057,26 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
 	else
 		return rc;
 
+	rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_LLQ, 0);
+	if (!rc)
+		memcpy(&get_feat_ctx->llq, &get_resp.u.llq,
+		       sizeof(get_resp.u.llq));
+	else if (rc == ENA_COM_UNSUPPORTED)
+		memset(&get_feat_ctx->llq, 0x0, sizeof(get_feat_ctx->llq));
+	else
+		return rc;
+
+	rc = ena_com_get_feature(ena_dev, &get_resp,
+				 ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG, 0);
+	if (!rc)
+		memcpy(&get_feat_ctx->ind_table, &get_resp.u.ind_table,
+		       sizeof(get_resp.u.ind_table));
+	else if (rc == ENA_COM_UNSUPPORTED)
+		memset(&get_feat_ctx->ind_table, 0x0,
+		       sizeof(get_feat_ctx->ind_table));
+	else
+		return rc;
+
 	return 0;
 }
 
@@ -1829,8 +2108,8 @@ void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data)
 	struct ena_admin_aenq_entry *aenq_e;
 	struct ena_admin_aenq_common_desc *aenq_common;
 	struct ena_com_aenq *aenq  = &dev->aenq;
-	ena_aenq_handler handler_cb;
 	unsigned long long timestamp;
+	ena_aenq_handler handler_cb;
 	u16 masked_head, processed = 0;
 	u8 phase;
 
@@ -1840,8 +2119,13 @@ void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data)
 	aenq_common = &aenq_e->aenq_common_desc;
 
 	/* Go over all the events */
-	while ((aenq_common->flags & ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK) ==
-		phase) {
+	while ((READ_ONCE8(aenq_common->flags) &
+		ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK) == phase) {
+		/* Make sure the phase bit (ownership) is as expected before
+		 * reading the rest of the descriptor.
+		 */
+		dma_rmb();
+
 		timestamp = (unsigned long long)aenq_common->timestamp_low |
 			((unsigned long long)aenq_common->timestamp_high << 32);
 		ENA_TOUCH(timestamp); /* In case debug is disabled */
@@ -1876,7 +2160,9 @@ void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data)
 
 	/* write the aenq doorbell after all AENQ descriptors were read */
 	mb();
-	ENA_REG_WRITE32(dev->bus, (u32)aenq->head, dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF);
+	ENA_REG_WRITE32_RELAXED(dev->bus, (u32)aenq->head,
+				dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF);
+	mmiowb();
 }
 
 int ena_com_dev_reset(struct ena_com_dev *ena_dev,
@@ -2022,7 +2308,7 @@ int ena_com_get_offload_settings(struct ena_com_dev *ena_dev,
 	struct ena_admin_get_feat_resp resp;
 
 	ret = ena_com_get_feature(ena_dev, &resp,
-				  ENA_ADMIN_STATELESS_OFFLOAD_CONFIG);
+				  ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0);
 	if (unlikely(ret)) {
 		ena_trc_err("Failed to get offload capabilities %d\n", ret);
 		return ret;
@@ -2051,7 +2337,7 @@ int ena_com_set_hash_function(struct ena_com_dev *ena_dev)
 
 	/* Validate hash function is supported */
 	ret = ena_com_get_feature(ena_dev, &get_resp,
-				  ENA_ADMIN_RSS_HASH_FUNCTION);
+				  ENA_ADMIN_RSS_HASH_FUNCTION, 0);
 	if (unlikely(ret))
 		return ret;
 
@@ -2111,7 +2397,7 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
 	rc = ena_com_get_feature_ex(ena_dev, &get_resp,
 				    ENA_ADMIN_RSS_HASH_FUNCTION,
 				    rss->hash_key_dma_addr,
-				    sizeof(*rss->hash_key));
+				    sizeof(*rss->hash_key), 0);
 	if (unlikely(rc))
 		return rc;
 
@@ -2162,7 +2448,7 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
 	rc = ena_com_get_feature_ex(ena_dev, &get_resp,
 				    ENA_ADMIN_RSS_HASH_FUNCTION,
 				    rss->hash_key_dma_addr,
-				    sizeof(*rss->hash_key));
+				    sizeof(*rss->hash_key), 0);
 	if (unlikely(rc))
 		return rc;
 
@@ -2187,7 +2473,7 @@ int ena_com_get_hash_ctrl(struct ena_com_dev *ena_dev,
 	rc = ena_com_get_feature_ex(ena_dev, &get_resp,
 				    ENA_ADMIN_RSS_HASH_INPUT,
 				    rss->hash_ctrl_dma_addr,
-				    sizeof(*rss->hash_ctrl));
+				    sizeof(*rss->hash_ctrl), 0);
 	if (unlikely(rc))
 		return rc;
 
@@ -2423,7 +2709,7 @@ int ena_com_indirect_table_get(struct ena_com_dev *ena_dev, u32 *ind_tbl)
 	rc = ena_com_get_feature_ex(ena_dev, &get_resp,
 				    ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG,
 				    rss->rss_ind_tbl_dma_addr,
-				    tbl_size);
+				    tbl_size, 0);
 	if (unlikely(rc))
 		return rc;
 
@@ -2490,6 +2776,10 @@ int ena_com_allocate_host_info(struct ena_com_dev *ena_dev)
 	if (unlikely(!host_attr->host_info))
 		return ENA_COM_NO_MEM;
 
+	host_attr->host_info->ena_spec_version = ((ENA_COMMON_SPEC_VERSION_MAJOR <<
+		ENA_REGS_VERSION_MAJOR_VERSION_SHIFT) |
+		(ENA_COMMON_SPEC_VERSION_MINOR));
+
 	return 0;
 }
 
@@ -2642,7 +2932,7 @@ int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
 	int rc;
 
 	rc = ena_com_get_feature(ena_dev, &get_resp,
-				 ENA_ADMIN_INTERRUPT_MODERATION);
+				 ENA_ADMIN_INTERRUPT_MODERATION, 0);
 
 	if (rc) {
 		if (rc == ENA_COM_UNSUPPORTED) {
@@ -2768,3 +3058,34 @@ void ena_com_get_intr_moderation_entry(struct ena_com_dev *ena_dev,
 	intr_moder_tbl[level].pkts_per_interval;
 	entry->bytes_per_interval = intr_moder_tbl[level].bytes_per_interval;
 }
+
+int ena_com_config_dev_mode(struct ena_com_dev *ena_dev,
+			    struct ena_admin_feature_llq_desc *llq_features,
+			    struct ena_llq_configurations *llq_default_cfg)
+{
+	int rc;
+	int size;
+
+	if (!llq_features->max_llq_num) {
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		return 0;
+	}
+
+	rc = ena_com_config_llq_info(ena_dev, llq_features, llq_default_cfg);
+	if (rc)
+		return rc;
+
+	/* Validate the descriptor is not too big */
+	size = ena_dev->tx_max_header_size;
+	size += ena_dev->llq_info.descs_num_before_header *
+		sizeof(struct ena_eth_io_tx_desc);
+
+	if (unlikely(ena_dev->llq_info.desc_list_entry_size < size)) {
+		ena_trc_err("the size of the LLQ entry is smaller than needed\n");
+		return ENA_COM_INVAL;
+	}
+
+	ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_DEV;
+
+	return 0;
+}
drivers/net/ena/base/ena_com.h +106 -5

206 lines not on this page · raw message

drivers/net/ena/base/ena_defs/ena_admin_defs.h +371 -196

798 lines not on this page · raw message

drivers/net/ena/base/ena_defs/ena_common_defs.h +2 -3
index 072e6c1f1..e02334072 100644
@@ -30,12 +30,11 @@
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-
 #ifndef _ENA_COMMON_H_
 #define _ENA_COMMON_H_
 
-#define ENA_COMMON_SPEC_VERSION_MAJOR	0 /*  */
-#define ENA_COMMON_SPEC_VERSION_MINOR	10 /*  */
+#define ENA_COMMON_SPEC_VERSION_MAJOR        2
+#define ENA_COMMON_SPEC_VERSION_MINOR        0
 
 /* ENA operates with 48-bit memory addresses. ena_mem_addr_t */
 struct ena_common_mem_addr {
drivers/net/ena/base/ena_defs/ena_eth_io_defs.h +126 -118

293 lines not on this page · raw message

drivers/net/ena/base/ena_defs/ena_gen_info.h +2 -3
index e87bcfd88..640d5aa3e 100644
@@ -30,6 +30,5 @@
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-
-#define	ENA_GEN_DATE	"Sun Oct 23 12:27:32 IDT 2016"
-#define	ENA_GEN_COMMIT	"79d82fa"
+#define	ENA_GEN_DATE	"Wed Sep 26 13:46:28 DST 2018"
+#define	ENA_GEN_COMMIT	"aac865f"
drivers/net/ena/base/ena_defs/ena_includes.h +0 -33
index 30a920a8e..5ea312f82 100644
@@ -1,36 +1,3 @@
-/*-
-* BSD LICENSE
-*
-* Copyright (c) 2015-2016 Amazon.com, Inc. or its affiliates.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in
-* the documentation and/or other materials provided with the
-* distribution.
-* * Neither the name of copyright holder nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
 #include "ena_common_defs.h"
 #include "ena_regs_defs.h"
 #include "ena_admin_defs.h"
drivers/net/ena/base/ena_defs/ena_regs_defs.h +97 -110

239 lines not on this page · raw message

drivers/net/ena/base/ena_eth_com.c +235 -99

471 lines not on this page · raw message

drivers/net/ena/base/ena_eth_com.h +81 -6

131 lines not on this page · raw message

drivers/net/ena/base/ena_plat.h +6 -6
index f829936b2..d57de057c 100644
@@ -35,21 +35,21 @@
 #define ENA_PLAT_H_
 
 #if defined(ENA_IPXE)
-#include "ena_plat_ipxe.h"
+#include <ena_plat_ipxe.h>
 #elif defined(__linux__)
 #if defined(__KERNEL__)
-#include "ena_plat_linux.h"
+#include <ena_plat_linux.h>
 #else
-#include "ena_plat_dpdk.h"
+#include <ena_plat_dpdk.h>
 #endif
 #elif defined(__FreeBSD__)
 #if defined(_KERNEL)
-#include "ena_plat_fbsd.h"
+#include <ena_plat_fbsd.h>
 #else
-#include "ena_plat_dpdk.h"
+#include <ena_plat_dpdk.h>
 #endif
 #elif defined(_WIN32)
-#include "ena_plat_windows.h"
+#include <ena_plat_windows.h>
 #else
 #error "Invalid platform"
 #endif
drivers/net/ena/base/ena_plat_dpdk.h +34 -1
index 900ba1a6b..902d91efb 100644
@@ -48,6 +48,7 @@
 #include <rte_log.h>
 #include <rte_malloc.h>
 #include <rte_memzone.h>
+#include <rte_prefetch.h>
 #include <rte_spinlock.h>
 
 #include <sys/time.h>

Lines of this file are not shown. View the raw message.

drivers/net/ena/ena_ethdev.c +2 -2
index 709ad2edb..667820806 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.14.1

Part of the diff is not shown here. View the raw message.

#2 lore raw

PATCH 2/20 net/ena: pass number of CPUs to the host info structure

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

The new ena_com allows the number of CPUs to be passed to the device in the host info structure.

---
 drivers/net/ena/ena_ethdev.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/ena/ena_ethdev.c +1 -0
index 667820806..5e9666f74 100644
@@ -437,6 +437,7 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev)
 		(DRV_MODULE_VER_MINOR << ENA_ADMIN_HOST_INFO_MINOR_SHIFT) |
 		(DRV_MODULE_VER_SUBMINOR <<
 			ENA_ADMIN_HOST_INFO_SUB_MINOR_SHIFT);
+	host_info->num_cpus = rte_lcore_count();
 
 	rc = ena_com_set_host_attributes(ena_dev);
 	if (rc) {
Signature · 1 line
2.14.1
#3 lore raw

PATCH 3/20 net/ena: add reset reason in rx error

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

Whenever the driver will receive too many descriptors from the device, it should trigger the device reset with reset reason set to ENA_REGS_RESET_TOO_MANY_RX_DESCS.

Fixes 241da076b1f7 ("net/ena: adjust error checking and cleaning")
---
 drivers/net/ena/ena_ethdev.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/net/ena/ena_ethdev.c +2 -0
index 5e9666f74..a47f5f7fa 100644
@@ -1910,6 +1910,8 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 				    &ena_rx_ctx);
 		if (unlikely(rc)) {
 			RTE_LOG(ERR, PMD, "ena_com_rx_pkt error %d\n", rc);
+			rx_ring->adapter->reset_reason =
+				ENA_REGS_RESET_TOO_MANY_RX_DESCS;
 			rx_ring->adapter->trigger_reset = true;
 			return 0;
 		}
Signature · 1 line
2.14.1
#4 lore raw

PATCH 4/20 net/ena: add hw queues depth setup

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

The device now allows driver to reconfigure Tx and Rx queues depth independently. Moreover, maximum size for Tx and Rx can be different. Those maximum values are received from the device.

After reset, previous ring configuration is restored.

If number of descriptor is set to RTE_ETH_DEV_FALLBACK_RX_RINGSIZE or RTE_ETH_DEV_FALLBACK_TX_RINGSIZE, the maximum value is restored.

Remove checks, if provided number is not too big, as this is done in generic functions (rte_eth_rx_queue_setup and rte_eth_tx_queue_setup).

Maximum number of segments is being set for Rx packets and provided to ena_com_rx_pkt() for validation.

Unused definitions were removed.

---
 drivers/net/ena/ena_ethdev.c | 125 ++++++++++++++++++++++++++++---------------
 drivers/net/ena/ena_ethdev.h |  11 +++-
 2 files changed, 93 insertions(+), 43 deletions(-)
drivers/net/ena/ena_ethdev.c +83 -42
index a47f5f7fa..617f85f02 100644
@@ -85,7 +85,6 @@
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
-#define ENA_MAX_RING_DESC	ENA_DEFAULT_RING_SIZE
 #define ENA_MIN_RING_DESC	128
 
 enum ethtool_stringset {
@@ -591,11 +590,12 @@ ena_dev_reset(struct rte_eth_dev *dev)
 	ena_com_admin_aenq_enable(ena_dev);
 
 	for (i = 0; i < nb_queues; ++i)
-		ena_rx_queue_setup(eth_dev, i, adapter->rx_ring_size, 0, NULL,
-			mb_pool_rx[i]);
+		ena_rx_queue_setup(eth_dev, i, adapter->rx_ring[i].ring_size, 0,
+			NULL, mb_pool_rx[i]);
 
 	for (i = 0; i < nb_queues; ++i)
-		ena_tx_queue_setup(eth_dev, i, adapter->tx_ring_size, 0, NULL);
+		ena_tx_queue_setup(eth_dev, i, adapter->tx_ring[i].ring_size, 0,
+			NULL);
 
 	adapter->trigger_reset = false;
 
@@ -935,34 +935,46 @@ static int ena_check_valid_conf(struct ena_adapter *adapter)
 }
 
 static int
-ena_calc_queue_size(struct ena_com_dev *ena_dev,
-		    u16 *max_tx_sgl_size,
-		    struct ena_com_dev_get_features_ctx *get_feat_ctx)
+ena_calc_queue_size(struct ena_calc_queue_size_ctx *ctx)
 {
-	uint32_t queue_size = ENA_DEFAULT_RING_SIZE;
-
-	queue_size = RTE_MIN(queue_size,
-			     get_feat_ctx->max_queues.max_cq_depth);
-	queue_size = RTE_MIN(queue_size,
-			     get_feat_ctx->max_queues.max_sq_depth);
-
-	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
-		queue_size = RTE_MIN(queue_size,
-				     get_feat_ctx->max_queues.max_legacy_llq_depth);
-
-	/* Round down to power of 2 */
-	if (!rte_is_power_of_2(queue_size))
-		queue_size = rte_align32pow2(queue_size >> 1);
-
-	if (unlikely(queue_size == 0)) {
+	uint32_t tx_queue_size, rx_queue_size;
+
+	if (ctx->ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
+		struct ena_admin_queue_ext_feature_fields *max_queue_ext =
+			&ctx->get_feat_ctx->max_queue_ext.max_queue_ext;
+		rx_queue_size = RTE_MIN(max_queue_ext->max_rx_cq_depth,
+			max_queue_ext->max_rx_sq_depth);
+		tx_queue_size = RTE_MIN(max_queue_ext->max_tx_cq_depth,
+			max_queue_ext->max_tx_sq_depth);
+		ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
+			max_queue_ext->max_per_packet_rx_descs);
+		ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
+			max_queue_ext->max_per_packet_tx_descs);
+	} else {
+		struct ena_admin_queue_feature_desc *max_queues =
+			&ctx->get_feat_ctx->max_queues;
+		rx_queue_size = RTE_MIN(max_queues->max_cq_depth,
+			max_queues->max_sq_depth);
+		tx_queue_size = rx_queue_size;
+		ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
+			max_queues->max_packet_tx_descs);
+		ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
+			max_queues->max_packet_rx_descs);
+	}
+
+	/* Round down to the nearest power of 2 */
+	rx_queue_size = rte_align32prevpow2(rx_queue_size);
+	tx_queue_size = rte_align32prevpow2(tx_queue_size);
+
+	if (unlikely(rx_queue_size == 0 || tx_queue_size == 0)) {
 		PMD_INIT_LOG(ERR, "Invalid queue size");
 		return -EFAULT;
 	}
 
-	*max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
-		get_feat_ctx->max_queues.max_packet_tx_descs);
+	ctx->rx_queue_size = rx_queue_size;
+	ctx->tx_queue_size = tx_queue_size;
 
-	return queue_size;
+	return 0;
 }
 
 static void ena_stats_restart(struct rte_eth_dev *dev)
@@ -1239,6 +1251,9 @@ static int ena_tx_queue_setup(struct rte_eth_dev *dev,
 		return -EINVAL;
 	}
 
+	if (nb_desc == RTE_ETH_DEV_FALLBACK_TX_RINGSIZE)
+		nb_desc = adapter->tx_ring_size;
+
 	txq->port_id = dev->data->port_id;
 	txq->next_to_clean = 0;
 	txq->next_to_use = 0;
@@ -1297,6 +1312,9 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev,
 		return ENA_COM_FAULT;
 	}
 
+	if (nb_desc == RTE_ETH_DEV_FALLBACK_RX_RINGSIZE)
+		nb_desc = adapter->rx_ring_size;
+
 	if (!rte_is_power_of_2(nb_desc)) {
 		RTE_LOG(ERR, PMD,
 			"Unsupported size of RX queue: %d is not a power of 2.",
@@ -1574,13 +1592,26 @@ static void ena_timer_wd_callback(__rte_unused struct rte_timer *timer,
 	}
 }
 
-static int ena_calc_io_queue_num(__rte_unused struct ena_com_dev *ena_dev,
+static int ena_calc_io_queue_num(struct ena_com_dev *ena_dev,
 				 struct ena_com_dev_get_features_ctx *get_feat_ctx)
 {
-	int io_sq_num, io_cq_num, io_queue_num;
+	uint32_t io_sq_num, io_cq_num, io_queue_num;
+
+	/* Regular queues capabilities */
+	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
+		struct ena_admin_queue_ext_feature_fields *max_queue_ext =
+			&get_feat_ctx->max_queue_ext.max_queue_ext;
+		io_sq_num = max_queue_ext->max_rx_sq_num;
+		io_sq_num = RTE_MIN(io_sq_num, max_queue_ext->max_tx_sq_num);
 
-	io_sq_num = get_feat_ctx->max_queues.max_sq_num;
-	io_cq_num = get_feat_ctx->max_queues.max_cq_num;
+		io_cq_num = max_queue_ext->max_rx_cq_num;
+		io_cq_num = RTE_MIN(io_cq_num, max_queue_ext->max_tx_cq_num);
+	} else {
+		struct ena_admin_queue_feature_desc *max_queues =
+			&get_feat_ctx->max_queues;
+		io_sq_num = max_queues->max_sq_num;
+		io_cq_num = max_queues->max_cq_num;
+	}
 
 	io_queue_num = RTE_MIN(io_sq_num, io_cq_num);
 
@@ -1594,14 +1625,14 @@ static int ena_calc_io_queue_num(__rte_unused struct ena_com_dev *ena_dev,
 
 static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 {
+	struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 };
 	struct rte_pci_device *pci_dev;
 	struct rte_intr_handle *intr_handle;
 	struct ena_adapter *adapter =
 		(struct ena_adapter *)(eth_dev->data->dev_private);
 	struct ena_com_dev *ena_dev = &adapter->ena_dev;
 	struct ena_com_dev_get_features_ctx get_feat_ctx;
-	int queue_size, rc;
-	u16 tx_sgl_size = 0;
+	int rc;
 
 	static int adapters_found;
 	bool wd_state;
@@ -1656,19 +1687,24 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 	adapter->wd_state = wd_state;
 
 	ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+
+	calc_queue_ctx.ena_dev = ena_dev;
+	calc_queue_ctx.get_feat_ctx = &get_feat_ctx;
+
 	adapter->num_queues = ena_calc_io_queue_num(ena_dev,
 						    &get_feat_ctx);
 
-	queue_size = ena_calc_queue_size(ena_dev, &tx_sgl_size, &get_feat_ctx);
-	if (queue_size <= 0 || adapter->num_queues <= 0) {
+	rc = ena_calc_queue_size(&calc_queue_ctx);
+	if (unlikely((rc != 0) || (adapter->num_queues <= 0))) {
 		rc = -EFAULT;
 		goto err_device_destroy;
 	}
 
-	adapter->tx_ring_size = queue_size;
-	adapter->rx_ring_size = queue_size;
+	adapter->tx_ring_size = calc_queue_ctx.tx_queue_size;
+	adapter->rx_ring_size = calc_queue_ctx.rx_queue_size;
 
-	adapter->max_tx_sgl_size = tx_sgl_size;
+	adapter->max_tx_sgl_size = calc_queue_ctx.max_tx_sgl_size;
+	adapter->max_rx_sgl_size = calc_queue_ctx.max_rx_sgl_size;
 
 	/* prepare ring structures */
 	ena_init_rings(adapter);
@@ -1785,6 +1821,7 @@ static void ena_init_rings(struct ena_adapter *adapter)
 		ring->type = ENA_RING_TYPE_RX;
 		ring->adapter = adapter;
 		ring->id = i;
+		ring->sgl_size = adapter->max_rx_sgl_size;
 	}
 }
 
@@ -1857,15 +1894,19 @@ static void ena_infos_get(struct rte_eth_dev *dev,
 	adapter->tx_supported_offloads = tx_feat;
 	adapter->rx_supported_offloads = rx_feat;
 
-	dev_info->rx_desc_lim.nb_max = ENA_MAX_RING_DESC;
+	dev_info->rx_desc_lim.nb_max = adapter->rx_ring_size;
 	dev_info->rx_desc_lim.nb_min = ENA_MIN_RING_DESC;
+	dev_info->rx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS,
+					adapter->max_rx_sgl_size);
+	dev_info->rx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS,
+					adapter->max_rx_sgl_size);
 
-	dev_info->tx_desc_lim.nb_max = ENA_MAX_RING_DESC;
+	dev_info->tx_desc_lim.nb_max = adapter->tx_ring_size;
 	dev_info->tx_desc_lim.nb_min = ENA_MIN_RING_DESC;
 	dev_info->tx_desc_lim.nb_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS,
-					feat.max_queues.max_packet_tx_descs);
+					adapter->max_tx_sgl_size);
 	dev_info->tx_desc_lim.nb_mtu_seg_max = RTE_MIN(ENA_PKT_MAX_BUFS,
-					feat.max_queues.max_packet_tx_descs);
+					adapter->max_tx_sgl_size);
 }
 
 static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
@@ -1901,7 +1942,7 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 	for (completed = 0; completed < nb_pkts; completed++) {
 		int segments = 0;
 
-		ena_rx_ctx.max_bufs = rx_ring->ring_size;
+		ena_rx_ctx.max_bufs = rx_ring->sgl_size;
 		ena_rx_ctx.ena_bufs = rx_ring->ena_bufs;
 		ena_rx_ctx.descs = 0;
 		/* receive packet context */
drivers/net/ena/ena_ethdev.h +10 -1
index 322e90ace..e6f7bd012 100644
@@ -45,7 +45,6 @@
 #define ENA_MEM_BAR	2
 
 #define ENA_MAX_NUM_QUEUES	128
-#define ENA_DEFAULT_RING_SIZE	(1024)
 #define ENA_MIN_FRAME_LEN	64
 #define ENA_NAME_MAX_LEN	20
 #define ENA_PKT_MAX_BUFS	17
@@ -71,6 +70,15 @@ struct ena_tx_buffer {
 	struct ena_com_buf bufs[ENA_PKT_MAX_BUFS];
 };
 
+struct ena_calc_queue_size_ctx {
+	struct ena_com_dev_get_features_ctx *get_feat_ctx;
+	struct ena_com_dev *ena_dev;
+	u16 rx_queue_size;
+	u16 tx_queue_size;
+	u16 max_tx_sgl_size;
+	u16 max_rx_sgl_size;
+};
+
 struct ena_ring {
 	u16 next_to_use;
 	u16 next_to_clean;
@@ -176,6 +184,7 @@ struct ena_adapter {
 	/* RX */
 	struct ena_ring rx_ring[ENA_MAX_NUM_QUEUES] __rte_cache_aligned;
 	int rx_ring_size;
+	u16 max_rx_sgl_size;
 
 	u16 num_queues;
 	u16 max_mtu;

--
2.14.1

#5 lore raw

PATCH 5/20 net/ena: skip packet with wrong req_id

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

When invalid req_id is received, the reset should be handled by the application, as it is indicating invalid rings state, so further Rx is not making any sense.

Fixes c2034976673d ("net/ena: add Rx out of order completion")
---
 drivers/net/ena/ena_ethdev.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/net/ena/ena_ethdev.c +2 -0
index 617f85f02..505d9bf30 100644
@@ -1988,6 +1988,8 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			segments++;
 			next_to_clean++;
 		}
+		if (unlikely(rc))
+			break;
 
 		/* fill mbuf attributes if any */
 		ena_rx_mbuf_prepare(mbuf_head, &ena_rx_ctx);
Signature · 1 line
2.14.1
#6 lore raw

PATCH 6/20 net/ena: add LLQv2 support

In reply to Michal Krawczyk

LLQ (Low Latency Queue) is the feature that allows pushing header directly to the device through PCI before even DMA is triggered. It reduces latency, bacause device can start preparing packet before payload is sent through DMA.

---
 drivers/net/ena/ena_ethdev.c | 220 ++++++++++++++++++++++++++++++++++++-------
 drivers/net/ena/ena_ethdev.h |   3 +
 2 files changed, 190 insertions(+), 33 deletions(-)
drivers/net/ena/ena_ethdev.c +187 -33
index 505d9bf30..73070ad96 100644
@@ -116,6 +116,9 @@ struct ena_stats {
 #define ENA_STAT_GLOBAL_ENTRY(stat) \
 	ENA_STAT_ENTRY(stat, dev)
 
+#define ENA_MAX_RING_SIZE_RX 1024
+#define ENA_MAX_RING_SIZE_TX 1024
+
 /*
  * Each rte_memzone should have unique name.
  * To satisfy it, count number of allocation and add it to name.
@@ -806,6 +809,9 @@ static void ena_tx_queue_release(void *queue)
 	ena_tx_queue_release_bufs(ring);
 
 	/* Free ring resources */
+	if (ring->push_buf_intermediate_buf)
+		rte_free(ring->push_buf_intermediate_buf);
+
 	if (ring->tx_buffer_info)
 		rte_free(ring->tx_buffer_info);
 
@@ -814,6 +820,7 @@ static void ena_tx_queue_release(void *queue)
 
 	ring->empty_tx_reqs = NULL;
 	ring->tx_buffer_info = NULL;
+	ring->push_buf_intermediate_buf = NULL;
 
 	ring->configured = 0;
 
@@ -937,15 +944,30 @@ static int ena_check_valid_conf(struct ena_adapter *adapter)
 static int
 ena_calc_queue_size(struct ena_calc_queue_size_ctx *ctx)
 {
-	uint32_t tx_queue_size, rx_queue_size;
+	struct ena_admin_feature_llq_desc *llq = &ctx->get_feat_ctx->llq;
+	struct ena_com_dev *ena_dev = ctx->ena_dev;
+	uint32_t tx_queue_size = ENA_MAX_RING_SIZE_TX;
+	uint32_t rx_queue_size = ENA_MAX_RING_SIZE_RX;
 
-	if (ctx->ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
+	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
 		struct ena_admin_queue_ext_feature_fields *max_queue_ext =
 			&ctx->get_feat_ctx->max_queue_ext.max_queue_ext;
-		rx_queue_size = RTE_MIN(max_queue_ext->max_rx_cq_depth,
+		rx_queue_size = RTE_MIN(rx_queue_size,
+			max_queue_ext->max_rx_cq_depth);
+		rx_queue_size = RTE_MIN(rx_queue_size,
 			max_queue_ext->max_rx_sq_depth);
-		tx_queue_size = RTE_MIN(max_queue_ext->max_tx_cq_depth,
-			max_queue_ext->max_tx_sq_depth);
+		tx_queue_size = RTE_MIN(tx_queue_size,
+			max_queue_ext->max_tx_cq_depth);
+
+		if (ena_dev->tx_mem_queue_type ==
+		    ENA_ADMIN_PLACEMENT_POLICY_DEV) {
+			tx_queue_size = RTE_MIN(tx_queue_size,
+				llq->max_llq_depth);
+		} else {
+			tx_queue_size = RTE_MIN(tx_queue_size,
+				max_queue_ext->max_tx_sq_depth);
+		}
+
 		ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
 			max_queue_ext->max_per_packet_rx_descs);
 		ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
@@ -953,9 +975,22 @@ ena_calc_queue_size(struct ena_calc_queue_size_ctx *ctx)
 	} else {
 		struct ena_admin_queue_feature_desc *max_queues =
 			&ctx->get_feat_ctx->max_queues;
-		rx_queue_size = RTE_MIN(max_queues->max_cq_depth,
+		rx_queue_size = RTE_MIN(rx_queue_size,
+			max_queues->max_cq_depth);
+		rx_queue_size = RTE_MIN(rx_queue_size,
 			max_queues->max_sq_depth);
-		tx_queue_size = rx_queue_size;
+		tx_queue_size = RTE_MIN(tx_queue_size,
+			max_queues->max_cq_depth);
+
+		if (ena_dev->tx_mem_queue_type ==
+		    ENA_ADMIN_PLACEMENT_POLICY_DEV) {
+			tx_queue_size = RTE_MIN(tx_queue_size,
+				llq->max_llq_depth);
+		} else {
+			tx_queue_size = RTE_MIN(tx_queue_size,
+				max_queues->max_sq_depth);
+		}
+
 		ctx->max_rx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
 			max_queues->max_packet_tx_descs);
 		ctx->max_tx_sgl_size = RTE_MIN(ENA_PKT_MAX_BUFS,
@@ -1277,6 +1312,17 @@ static int ena_tx_queue_setup(struct rte_eth_dev *dev,
 		return -ENOMEM;
 	}
 
+	txq->push_buf_intermediate_buf =
+		rte_zmalloc("txq->push_buf_intermediate_buf",
+			    txq->tx_max_header_size,
+			    RTE_CACHE_LINE_SIZE);
+	if (!txq->push_buf_intermediate_buf) {
+		RTE_LOG(ERR, PMD, "failed to alloc push buff for LLQ\n");
+		rte_free(txq->tx_buffer_info);
+		rte_free(txq->empty_tx_reqs);
+		return -ENOMEM;
+	}
+
 	for (i = 0; i < txq->ring_size; i++)
 		txq->empty_tx_reqs[i] = i;
 
@@ -1592,28 +1638,87 @@ static void ena_timer_wd_callback(__rte_unused struct rte_timer *timer,
 	}
 }
 
+static inline void
+set_default_llq_configurations(struct ena_llq_configurations *llq_config)
+{
+	llq_config->llq_header_location = ENA_ADMIN_INLINE_HEADER;
+	llq_config->llq_ring_entry_size = ENA_ADMIN_LIST_ENTRY_SIZE_128B;
+	llq_config->llq_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY;
+	llq_config->llq_num_decs_before_header =
+		ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2;
+	llq_config->llq_ring_entry_size_value = 128;
+}
+
+static int
+ena_set_queues_placement_policy(struct ena_adapter *adapter,
+				struct ena_com_dev *ena_dev,
+				struct ena_admin_feature_llq_desc *llq,
+				struct ena_llq_configurations *llq_default_configurations)
+{
+	int rc;
+	u32 llq_feature_mask;
+
+	llq_feature_mask = 1 << ENA_ADMIN_LLQ;
+	if (!(ena_dev->supported_features & llq_feature_mask)) {
+		RTE_LOG(INFO, PMD,
+			"LLQ is not supported. Fallback to host mode policy.\n");
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		return 0;
+	}
+
+	rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations);
+	if (unlikely(rc)) {
+		PMD_INIT_LOG(WARNING, "Failed to config dev mode. "
+			"Fallback to host mode policy.\n");
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		return 0;
+	}
+
+	/* Nothing to config, exit */
+	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
+		return 0;
+
+	if (!adapter->dev_mem_base) {
+		RTE_LOG(ERR, PMD, "Unable to access LLQ bar resource. "
+			"Fallback to host mode policy.\n.");
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		return 0;
+	}
+
+	ena_dev->mem_bar = adapter->dev_mem_base;
+
+	return 0;
+}
+
 static int ena_calc_io_queue_num(struct ena_com_dev *ena_dev,
 				 struct ena_com_dev_get_features_ctx *get_feat_ctx)
 {
-	uint32_t io_sq_num, io_cq_num, io_queue_num;
+	uint32_t io_tx_sq_num, io_tx_cq_num, io_rx_num, io_queue_num;
 
 	/* Regular queues capabilities */
 	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
 		struct ena_admin_queue_ext_feature_fields *max_queue_ext =
 			&get_feat_ctx->max_queue_ext.max_queue_ext;
-		io_sq_num = max_queue_ext->max_rx_sq_num;
-		io_sq_num = RTE_MIN(io_sq_num, max_queue_ext->max_tx_sq_num);
-
-		io_cq_num = max_queue_ext->max_rx_cq_num;
-		io_cq_num = RTE_MIN(io_cq_num, max_queue_ext->max_tx_cq_num);
+		io_rx_num = RTE_MIN(max_queue_ext->max_rx_sq_num,
+				    max_queue_ext->max_rx_cq_num);
+		io_tx_sq_num = max_queue_ext->max_tx_sq_num;
+		io_tx_cq_num = max_queue_ext->max_tx_cq_num;
 	} else {
 		struct ena_admin_queue_feature_desc *max_queues =
 			&get_feat_ctx->max_queues;
-		io_sq_num = max_queues->max_sq_num;
-		io_cq_num = max_queues->max_cq_num;
+		io_tx_sq_num = max_queues->max_sq_num;
+		io_tx_cq_num = max_queues->max_cq_num;
+		io_rx_num = RTE_MIN(io_tx_sq_num, io_tx_cq_num);
 	}
 
-	io_queue_num = RTE_MIN(io_sq_num, io_cq_num);
+	/* In case of LLQ use the llq number in the get feature cmd */
+	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
+		io_tx_sq_num = get_feat_ctx->llq.max_llq_num;
+
+	io_queue_num = RTE_MIN(rte_lcore_count(), ENA_MAX_NUM_IO_QUEUES);
+	io_queue_num = RTE_MIN(io_queue_num, io_rx_num);
+	io_queue_num = RTE_MIN(io_queue_num, io_tx_sq_num);
+	io_queue_num = RTE_MIN(io_queue_num, io_tx_cq_num);
 
 	if (unlikely(io_queue_num == 0)) {
 		RTE_LOG(ERR, PMD, "Number of IO queues should not be 0\n");
@@ -1632,6 +1737,8 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 		(struct ena_adapter *)(eth_dev->data->dev_private);
 	struct ena_com_dev *ena_dev = &adapter->ena_dev;
 	struct ena_com_dev_get_features_ctx get_feat_ctx;
+	struct ena_llq_configurations llq_config;
+	const char *queue_type_str;
 	int rc;
 
 	static int adapters_found;
@@ -1686,11 +1793,22 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 	}
 	adapter->wd_state = wd_state;
 
-	ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+	set_default_llq_configurations(&llq_config);
+	rc = ena_set_queues_placement_policy(adapter, ena_dev,
+					     &get_feat_ctx.llq, &llq_config);
+	if (unlikely(rc)) {
+		PMD_INIT_LOG(CRIT, "Failed to set placement policy");
+		return rc;
+	}
+
+	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
+		queue_type_str = "Regular";
+	else
+		queue_type_str = "Low latency";
+	RTE_LOG(INFO, PMD, "Placement policy: %s\n", queue_type_str);
 
 	calc_queue_ctx.ena_dev = ena_dev;
 	calc_queue_ctx.get_feat_ctx = &get_feat_ctx;
-
 	adapter->num_queues = ena_calc_io_queue_num(ena_dev,
 						    &get_feat_ctx);
 
@@ -2106,13 +2224,21 @@ static void ena_update_hints(struct ena_adapter *adapter,
 static int ena_check_and_linearize_mbuf(struct ena_ring *tx_ring,
 					struct rte_mbuf *mbuf)
 {
-	int num_segments, rc;
+	struct ena_com_dev *ena_dev;
+	int num_segments, header_len, rc;
 
+	ena_dev = &tx_ring->adapter->ena_dev;
 	num_segments = mbuf->nb_segs;
+	header_len = mbuf->data_len;
 
 	if (likely(num_segments < tx_ring->sgl_size))
 		return 0;
 
+	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV &&
+	    (num_segments == tx_ring->sgl_size) &&
+	    (header_len < tx_ring->tx_max_header_size))
+		return 0;
+
 	rc = rte_pktmbuf_linearize(mbuf);
 	if (unlikely(rc))
 		RTE_LOG(WARNING, PMD, "Mbuf linearize failed\n");
@@ -2127,6 +2253,7 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 	uint16_t next_to_use = tx_ring->next_to_use;
 	uint16_t next_to_clean = tx_ring->next_to_clean;
 	struct rte_mbuf *mbuf;
+	uint16_t seg_len;
 	unsigned int ring_size = tx_ring->ring_size;
 	unsigned int ring_mask = ring_size - 1;
 	struct ena_com_tx_ctx ena_tx_ctx;
@@ -2134,6 +2261,8 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 	struct ena_com_buf *ebuf;
 	uint16_t rc, req_id, total_tx_descs = 0;
 	uint16_t sent_idx = 0, empty_tx_reqs;
+	uint16_t push_len = 0;
+	uint16_t delta = 0;
 	int nb_hw_desc;
 
 	/* Check adapter state */
@@ -2166,17 +2295,32 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		       sizeof(struct ena_com_tx_meta));
 		ena_tx_ctx.ena_bufs = ebuf;
 		ena_tx_ctx.req_id = req_id;
+
+		delta = 0;
+		seg_len = mbuf->data_len;
+
 		if (tx_ring->tx_mem_queue_type ==
 				ENA_ADMIN_PLACEMENT_POLICY_DEV) {
-			/* prepare the push buffer with
-			 * virtual address of the data
-			 */
-			ena_tx_ctx.header_len =
-				RTE_MIN(mbuf->data_len,
-					tx_ring->tx_max_header_size);
-			ena_tx_ctx.push_header =
-				(void *)((char *)mbuf->buf_addr +
-					 mbuf->data_off);
+			push_len = RTE_MIN(mbuf->pkt_len,
+					   tx_ring->tx_max_header_size);
+			ena_tx_ctx.header_len = push_len;
+
+			if (likely(push_len <= seg_len)) {
+				/* If the push header is in the single segment,
+				 * then just point it to the 1st mbuf data.
+				 */
+				ena_tx_ctx.push_header =
+					rte_pktmbuf_mtod(mbuf, uint8_t *);
+			} else {
+				/* If the push header lays in the several
+				 * segments, copy it to the intermediate buffer.
+				 */
+				rte_pktmbuf_read(mbuf, 0, push_len,
+					tx_ring->push_buf_intermediate_buf);
+				ena_tx_ctx.push_header =
+					tx_ring->push_buf_intermediate_buf;
+				delta = push_len - seg_len;
+			}
 		} /* there's no else as we take advantage of memset zeroing */
 
 		/* Set TX offloads flags, if applicable */
@@ -2191,20 +2335,30 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		/* Process first segment taking into
 		 * consideration pushed header
 		 */
-		if (mbuf->data_len > ena_tx_ctx.header_len) {
+		if (seg_len > push_len) {
 			ebuf->paddr = mbuf->buf_iova +
 				      mbuf->data_off +
-				      ena_tx_ctx.header_len;
-			ebuf->len = mbuf->data_len - ena_tx_ctx.header_len;
+				      push_len;
+			ebuf->len = seg_len - push_len;
 			ebuf++;
 			tx_info->num_of_bufs++;
 		}
 
 		while ((mbuf = mbuf->next) != NULL) {
-			ebuf->paddr = mbuf->buf_iova + mbuf->data_off;
-			ebuf->len = mbuf->data_len;
+			seg_len = mbuf->data_len;
+
+			/* Skip mbufs if whole data is pushed as a header */
+			if (unlikely(delta > seg_len)) {
+				delta -= seg_len;
+				continue;
+			}
+
+			ebuf->paddr = mbuf->buf_iova + mbuf->data_off + delta;
+			ebuf->len = seg_len - delta;
 			ebuf++;
 			tx_info->num_of_bufs++;
+
+			delta = 0;
 		}
 
 		ena_tx_ctx.num_bufs = tx_info->num_of_bufs;
drivers/net/ena/ena_ethdev.h +3 -0
index e6f7bd012..713cdea97 100644
@@ -110,6 +110,9 @@ struct ena_ring {
 	/* Max length PMD can push to device for LLQ */
 	uint8_t tx_max_header_size;
 	int configured;
+
+	uint8_t *push_buf_intermediate_buf;
+
 	struct ena_adapter *adapter;
 	uint64_t offloads;
 	u16 sgl_size;
Signature · 1 line
2.14.1
#7 lore raw

PATCH 7/20 net/ena: increase maximum Rx ring size

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

Some of ENA devices supports 8k Rx rings. Maximum supported size is received upon device initialization.
As ENA_DEFAULT_RING_SIZE_RX macro is upper limit, it needs to be adjusted.

---
 drivers/net/ena/ena_ethdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ena/ena_ethdev.c +1 -1
index 73070ad96..f83552377 100644
@@ -116,7 +116,7 @@ struct ena_stats {
 #define ENA_STAT_GLOBAL_ENTRY(stat) \
 	ENA_STAT_ENTRY(stat, dev)
 
-#define ENA_MAX_RING_SIZE_RX 1024
+#define ENA_MAX_RING_SIZE_RX 8192
 #define ENA_MAX_RING_SIZE_TX 1024
 
 /*
Signature · 1 line
2.14.1
#8 lore raw

PATCH 8/20 net/ena: call additional doorbells if needed

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

Before sending next packet, check if calling doorbell is needed.

---
 drivers/net/ena/ena_ethdev.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/net/ena/ena_ethdev.c +10 -1
index f83552377..5f7dec086 100644
@@ -2363,7 +2363,16 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 		ena_tx_ctx.num_bufs = tx_info->num_of_bufs;
 
-		/* Write data to device */
+		if (ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq,
+					       &ena_tx_ctx)) {
+			RTE_LOG(DEBUG, PMD, "llq tx max burst size of queue %d"
+				" achieved, writing doorbell to send burst\n",
+				tx_ring->id);
+			rte_wmb();
+			ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq);
+		}
+
+		/* prepare the packet's descriptors to dma engine */
 		rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq,
 					&ena_tx_ctx, &nb_hw_desc);
 		if (unlikely(rc))
Signature · 1 line
2.14.1
#9 lore raw

PATCH 9/20 net/ena: destroy queues if start failed

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

If start function fails, previously created queues have to be removed.

ena_queue_restart_all() and ena_queue_restart() are renamed to ena_queue_start_all() and ena_queue_start().

ena_free_io_queues_all() is renamed to ena_queue_stop_all().

Fixes df238f84c0a2 ("net/ena: recreate HW IO rings on start and stop")
---
 drivers/net/ena/ena_ethdev.c | 95 ++++++++++++++++++++++++++++----------------
 1 file changed, 60 insertions(+), 35 deletions(-)
drivers/net/ena/ena_ethdev.c +60 -35
index 5f7dec086..deb97151d 100644
@@ -244,10 +244,12 @@ static void ena_tx_queue_release_bufs(struct ena_ring *ring);
 static int ena_link_update(struct rte_eth_dev *dev,
 			   int wait_to_complete);
 static int ena_create_io_queue(struct ena_ring *ring);
-static void ena_free_io_queues_all(struct ena_adapter *adapter);
-static int ena_queue_restart(struct ena_ring *ring);
-static int ena_queue_restart_all(struct rte_eth_dev *dev,
-				 enum ena_ring_type ring_type);
+static void ena_queue_stop(struct ena_ring *ring);
+static void ena_queue_stop_all(struct rte_eth_dev *dev,
+			      enum ena_ring_type ring_type);
+static int ena_queue_start(struct ena_ring *ring);
+static int ena_queue_start_all(struct rte_eth_dev *dev,
+			       enum ena_ring_type ring_type);
 static void ena_stats_restart(struct rte_eth_dev *dev);
 static void ena_infos_get(struct rte_eth_dev *dev,
 			  struct rte_eth_dev_info *dev_info);
@@ -805,9 +807,6 @@ static void ena_tx_queue_release(void *queue)
 	ena_assert_msg(ring->adapter->state != ENA_ADAPTER_STATE_RUNNING,
 		       "API violation");
 
-	/* Free all bufs */
-	ena_tx_queue_release_bufs(ring);
-
 	/* Free ring resources */
 	if (ring->push_buf_intermediate_buf)
 		rte_free(ring->push_buf_intermediate_buf);
@@ -872,8 +871,8 @@ static int ena_link_update(struct rte_eth_dev *dev,
 	return 0;
 }
 
-static int ena_queue_restart_all(struct rte_eth_dev *dev,
-				 enum ena_ring_type ring_type)
+static int ena_queue_start_all(struct rte_eth_dev *dev,
+			       enum ena_ring_type ring_type)
 {
 	struct ena_adapter *adapter =
 		(struct ena_adapter *)(dev->data->dev_private);
@@ -901,18 +900,25 @@ static int ena_queue_restart_all(struct rte_eth_dev *dev,
 					"Inconsistent state of tx queues\n");
 			}
 
-			rc = ena_queue_restart(&queues[i]);
+			rc = ena_queue_start(&queues[i]);
 
 			if (rc) {
 				PMD_INIT_LOG(ERR,
-					     "failed to restart queue %d type(%d)",
+					     "failed to start queue %d type(%d)",
 					     i, ring_type);
-				return rc;
+				goto err;
 			}
 		}
 	}
 
 	return 0;
+
+err:
+	while (i--)
+		if (queues[i].configured)
+			ena_queue_stop(&queues[i]);
+
+	return rc;
 }
 
 static uint32_t ena_get_mtu_conf(struct ena_adapter *adapter)
@@ -1101,19 +1107,19 @@ static int ena_start(struct rte_eth_dev *dev)
 	if (rc)
 		return rc;
 
-	rc = ena_queue_restart_all(dev, ENA_RING_TYPE_RX);
+	rc = ena_queue_start_all(dev, ENA_RING_TYPE_RX);
 	if (rc)
 		return rc;
 
-	rc = ena_queue_restart_all(dev, ENA_RING_TYPE_TX);
+	rc = ena_queue_start_all(dev, ENA_RING_TYPE_TX);
 	if (rc)
-		return rc;
+		goto err_start_tx;
 
 	if (adapter->rte_dev->data->dev_conf.rxmode.mq_mode &
 	    ETH_MQ_RX_RSS_FLAG && adapter->rte_dev->data->nb_rx_queues > 0) {
 		rc = ena_rss_init_default(adapter);
 		if (rc)
-			return rc;
+			goto err_rss_init;
 	}
 
 	ena_stats_restart(dev);
@@ -1128,6 +1134,12 @@ static int ena_start(struct rte_eth_dev *dev)
 	adapter->state = ENA_ADAPTER_STATE_RUNNING;
 
 	return 0;
+
+err_rss_init:
+	ena_queue_stop_all(dev, ENA_RING_TYPE_TX);
+err_start_tx:
+	ena_queue_stop_all(dev, ENA_RING_TYPE_RX);
+	return rc;
 }
 
 static void ena_stop(struct rte_eth_dev *dev)
@@ -1136,7 +1148,8 @@ static void ena_stop(struct rte_eth_dev *dev)
 		(struct ena_adapter *)(dev->data->dev_private);
 
 	rte_timer_stop_sync(&adapter->timer_wd);
-	ena_free_io_queues_all(adapter);
+	ena_queue_stop_all(dev, ENA_RING_TYPE_TX);
+	ena_queue_stop_all(dev, ENA_RING_TYPE_RX);
 
 	adapter->state = ENA_ADAPTER_STATE_STOPPED;
 }
@@ -1199,36 +1212,46 @@ static int ena_create_io_queue(struct ena_ring *ring)
 	return 0;
 }
 
-static void ena_free_io_queues_all(struct ena_adapter *adapter)
+static void ena_queue_stop(struct ena_ring *ring)
 {
-	struct rte_eth_dev *eth_dev = adapter->rte_dev;
-	struct ena_com_dev *ena_dev = &adapter->ena_dev;
-	int i;
-	uint16_t ena_qid;
-	uint16_t nb_rxq = eth_dev->data->nb_rx_queues;
-	uint16_t nb_txq = eth_dev->data->nb_tx_queues;
-
-	for (i = 0; i < nb_txq; ++i) {
-		ena_qid = ENA_IO_TXQ_IDX(i);
-		ena_com_destroy_io_queue(ena_dev, ena_qid);
+	struct ena_com_dev *ena_dev = &ring->adapter->ena_dev;
 
-		ena_tx_queue_release_bufs(&adapter->tx_ring[i]);
+	if (ring->type == ENA_RING_TYPE_RX) {
+		ena_com_destroy_io_queue(ena_dev, ENA_IO_RXQ_IDX(ring->id));
+		ena_rx_queue_release_bufs(ring);
+	} else {
+		ena_com_destroy_io_queue(ena_dev, ENA_IO_TXQ_IDX(ring->id));
+		ena_tx_queue_release_bufs(ring);
 	}
+}
 
-	for (i = 0; i < nb_rxq; ++i) {
-		ena_qid = ENA_IO_RXQ_IDX(i);
-		ena_com_destroy_io_queue(ena_dev, ena_qid);
+static void ena_queue_stop_all(struct rte_eth_dev *dev,
+			      enum ena_ring_type ring_type)
+{
+	struct ena_adapter *adapter =
+		(struct ena_adapter *)(dev->data->dev_private);
+	struct ena_ring *queues = NULL;
+	uint16_t nb_queues, i;
 
-		ena_rx_queue_release_bufs(&adapter->rx_ring[i]);
+	if (ring_type == ENA_RING_TYPE_RX) {
+		queues = adapter->rx_ring;
+		nb_queues = dev->data->nb_rx_queues;
+	} else {
+		queues = adapter->tx_ring;
+		nb_queues = dev->data->nb_tx_queues;
 	}
+
+	for (i = 0; i < nb_queues; ++i)
+		if (queues[i].configured)
+			ena_queue_stop(&queues[i]);
 }
 
-static int ena_queue_restart(struct ena_ring *ring)
+static int ena_queue_start(struct ena_ring *ring)
 {
 	int rc, bufs_num;
 
 	ena_assert_msg(ring->configured == 1,
-		       "Trying to restart unconfigured queue\n");
+		       "Trying to start unconfigured queue\n");
 
 	rc = ena_create_io_queue(ring);
 	if (rc) {
@@ -1245,6 +1268,8 @@ static int ena_queue_restart(struct ena_ring *ring)
 	bufs_num = ring->ring_size - 1;
 	rc = ena_populate_rx_queue(ring, bufs_num);
 	if (rc != bufs_num) {
+		ena_com_destroy_io_queue(&ring->adapter->ena_dev,
+					 ENA_IO_RXQ_IDX(ring->id));
 		PMD_INIT_LOG(ERR, "Failed to populate rx ring !");
 		return ENA_COM_FAULT;
 	}
Signature · 1 line
2.14.1
#10 lore raw

PATCH 10/20 net/ena: reset should not reconfigure queues

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

Reset function should return the port to initial state, in which no Tx and Rx queues are setup. Then application should reconfigure the queues.

According to DPDK documentation the rte_eth_dev_reset() itself is a generic function which only does some hardware reset operations through calling dev_unint() and dev_init().

ena_com_dev_reset which perform NIC registers reset should be called during stop.

Fixes 2081d5e2e92d ("net/ena: add reset routine")
---
 drivers/net/ena/ena_ethdev.c | 108 +++++++++++++++----------------------------
 1 file changed, 38 insertions(+), 70 deletions(-)
drivers/net/ena/ena_ethdev.c +38 -70
index deb97151d..3715619a7 100644
@@ -262,6 +262,8 @@ static int ena_rss_reta_query(struct rte_eth_dev *dev,
 static int ena_get_sset_count(struct rte_eth_dev *dev, int sset);
 static void ena_interrupt_handler_rte(void *cb_arg);
 static void ena_timer_wd_callback(struct rte_timer *timer, void *arg);
+static void ena_destroy_device(struct rte_eth_dev *eth_dev);
+static int eth_ena_dev_init(struct rte_eth_dev *eth_dev);
 
 static const struct eth_dev_ops ena_dev_ops = {
 	.dev_configure        = ena_dev_configure,
@@ -546,65 +548,14 @@ static void ena_close(struct rte_eth_dev *dev)
 static int
 ena_dev_reset(struct rte_eth_dev *dev)
 {
-	struct rte_mempool *mb_pool_rx[ENA_MAX_NUM_QUEUES];
-	struct rte_eth_dev *eth_dev;
-	struct rte_pci_device *pci_dev;
-	struct rte_intr_handle *intr_handle;
-	struct ena_com_dev *ena_dev;
-	struct ena_com_dev_get_features_ctx get_feat_ctx;
-	struct ena_adapter *adapter;
-	int nb_queues;
-	int rc, i;
-	bool wd_state;
-
-	adapter = (struct ena_adapter *)(dev->data->dev_private);
-	ena_dev = &adapter->ena_dev;
-	eth_dev = adapter->rte_dev;
-	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
-	intr_handle = &pci_dev->intr_handle;
-	nb_queues = eth_dev->data->nb_rx_queues;
-
-	ena_com_set_admin_running_state(ena_dev, false);
+	int rc = 0;
 
-	rc = ena_com_dev_reset(ena_dev, adapter->reset_reason);
+	ena_destroy_device(dev);
+	rc = eth_ena_dev_init(dev);
 	if (rc)
-		RTE_LOG(ERR, PMD, "Device reset failed\n");
-
-	for (i = 0; i < nb_queues; i++)
-		mb_pool_rx[i] = adapter->rx_ring[i].mb_pool;
-
-	ena_rx_queue_release_all(eth_dev);
-	ena_tx_queue_release_all(eth_dev);
-
-	rte_intr_disable(intr_handle);
-
-	ena_com_abort_admin_commands(ena_dev);
-	ena_com_wait_for_abort_completion(ena_dev);
-	ena_com_admin_destroy(ena_dev);
-	ena_com_mmio_reg_read_request_destroy(ena_dev);
-
-	rc = ena_device_init(ena_dev, &get_feat_ctx, &wd_state);
-	if (rc) {
 		PMD_INIT_LOG(CRIT, "Cannot initialize device\n");
-		return rc;
-	}
-	adapter->wd_state = wd_state;
-
-	rte_intr_enable(intr_handle);
-	ena_com_set_admin_polling_mode(ena_dev, false);
-	ena_com_admin_aenq_enable(ena_dev);
-
-	for (i = 0; i < nb_queues; ++i)
-		ena_rx_queue_setup(eth_dev, i, adapter->rx_ring[i].ring_size, 0,
-			NULL, mb_pool_rx[i]);
 
-	for (i = 0; i < nb_queues; ++i)
-		ena_tx_queue_setup(eth_dev, i, adapter->tx_ring[i].ring_size, 0,
-			NULL);
-
-	adapter->trigger_reset = false;
-
-	return 0;
+	return rc;
 }
 
 static int ena_rss_reta_update(struct rte_eth_dev *dev,
@@ -774,11 +725,6 @@ static void ena_rx_queue_release(void *queue)
 {
 	struct ena_ring *ring = (struct ena_ring *)queue;
 
-	ena_assert_msg(ring->configured,
-		       "API violation - releasing not configured queue");
-	ena_assert_msg(ring->adapter->state != ENA_ADAPTER_STATE_RUNNING,
-		       "API violation");
-
 	/* Free ring resources */
 	if (ring->rx_buffer_info)
 		rte_free(ring->rx_buffer_info);
@@ -802,11 +748,6 @@ static void ena_tx_queue_release(void *queue)
 {
 	struct ena_ring *ring = (struct ena_ring *)queue;
 
-	ena_assert_msg(ring->configured,
-		       "API violation. Releasing not configured queue");
-	ena_assert_msg(ring->adapter->state != ENA_ADAPTER_STATE_RUNNING,
-		       "API violation");
-
 	/* Free ring resources */
 	if (ring->push_buf_intermediate_buf)
 		rte_free(ring->push_buf_intermediate_buf);
@@ -1146,11 +1087,19 @@ static void ena_stop(struct rte_eth_dev *dev)
 {
 	struct ena_adapter *adapter =
 		(struct ena_adapter *)(dev->data->dev_private);
+	struct ena_com_dev *ena_dev = &adapter->ena_dev;
+	int rc;
 
 	rte_timer_stop_sync(&adapter->timer_wd);
 	ena_queue_stop_all(dev, ENA_RING_TYPE_TX);
 	ena_queue_stop_all(dev, ENA_RING_TYPE_RX);
 
+	if (adapter->trigger_reset) {
+		rc = ena_com_dev_reset(ena_dev, adapter->reset_reason);
+		if (rc)
+			RTE_LOG(ERR, PMD, "Device reset failed rc=%d\n", rc);
+	}
+
 	adapter->state = ENA_ADAPTER_STATE_STOPPED;
 }
 
@@ -1908,24 +1857,43 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 	return rc;
 }
 
-static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev)
+static void ena_destroy_device(struct rte_eth_dev *eth_dev)
 {
 	struct ena_adapter *adapter =
 		(struct ena_adapter *)(eth_dev->data->dev_private);
+	struct ena_com_dev *ena_dev = &adapter->ena_dev;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return 0;
+	if (adapter->state == ENA_ADAPTER_STATE_FREE)
+		return;
+
+	ena_com_set_admin_running_state(ena_dev, false);
 
 	if (adapter->state != ENA_ADAPTER_STATE_CLOSED)
 		ena_close(eth_dev);
 
+	ena_com_delete_debug_area(ena_dev);
+	ena_com_delete_host_info(ena_dev);
+
+	ena_com_abort_admin_commands(ena_dev);
+	ena_com_wait_for_abort_completion(ena_dev);
+	ena_com_admin_destroy(ena_dev);
+	ena_com_mmio_reg_read_request_destroy(ena_dev);
+
+	adapter->state = ENA_ADAPTER_STATE_FREE;
+}
+
+static int eth_ena_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	ena_destroy_device(eth_dev);
+
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->tx_pkt_prepare = NULL;
 
-	adapter->state = ENA_ADAPTER_STATE_FREE;
-
 	return 0;
 }
 
Signature · 1 line
2.14.1
#11 lore raw

PATCH 11/20 net/ena: adjust new line in log messages

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

Only PMD_*_LOG is adding new line character to the log message. All printouts were adjusted for consistency.

---
 drivers/net/ena/ena_ethdev.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)
drivers/net/ena/ena_ethdev.c +14 -14
index 3715619a7..5adc87355 100644
@@ -553,7 +553,7 @@ ena_dev_reset(struct rte_eth_dev *dev)
 	ena_destroy_device(dev);
 	rc = eth_ena_dev_init(dev);
 	if (rc)
-		PMD_INIT_LOG(CRIT, "Cannot initialize device\n");
+		PMD_INIT_LOG(CRIT, "Cannot initialize device");
 
 	return rc;
 }
@@ -880,7 +880,7 @@ static int ena_check_valid_conf(struct ena_adapter *adapter)
 
 	if (max_frame_len > adapter->max_mtu || max_frame_len < ENA_MIN_MTU) {
 		PMD_INIT_LOG(ERR, "Unsupported MTU of %d. "
-				  "max mtu: %d, min mtu: %d\n",
+				  "max mtu: %d, min mtu: %d",
 			     max_frame_len, adapter->max_mtu, ENA_MIN_MTU);
 		return ENA_COM_UNSUPPORTED;
 	}
@@ -984,7 +984,7 @@ static int ena_stats_get(struct rte_eth_dev *dev,
 	memset(&ena_stats, 0, sizeof(ena_stats));
 	rc = ena_com_get_dev_basic_stats(ena_dev, &ena_stats);
 	if (unlikely(rc)) {
-		RTE_LOG(ERR, PMD, "Could not retrieve statistics from ENA");
+		RTE_LOG(ERR, PMD, "Could not retrieve statistics from ENA\n");
 		return rc;
 	}
 
@@ -1013,12 +1013,12 @@ static int ena_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	struct ena_com_dev *ena_dev;
 	int rc = 0;
 
-	ena_assert_msg(dev->data != NULL, "Uninitialized device");
-	ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device");
+	ena_assert_msg(dev->data != NULL, "Uninitialized device\n");
+	ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n");
 	adapter = (struct ena_adapter *)(dev->data->dev_private);
 
 	ena_dev = &adapter->ena_dev;
-	ena_assert_msg(ena_dev != NULL, "Uninitialized device");
+	ena_assert_msg(ena_dev != NULL, "Uninitialized device\n");
 
 	if (mtu > ena_get_mtu_conf(adapter) || mtu < ENA_MIN_MTU) {
 		RTE_LOG(ERR, PMD,
@@ -1204,7 +1204,7 @@ static int ena_queue_start(struct ena_ring *ring)
 
 	rc = ena_create_io_queue(ring);
 	if (rc) {
-		PMD_INIT_LOG(ERR, "Failed to create IO queue!\n");
+		PMD_INIT_LOG(ERR, "Failed to create IO queue!");
 		return rc;
 	}
 
@@ -1248,7 +1248,7 @@ static int ena_tx_queue_setup(struct rte_eth_dev *dev,
 
 	if (!rte_is_power_of_2(nb_desc)) {
 		RTE_LOG(ERR, PMD,
-			"Unsupported size of TX queue: %d is not a power of 2.",
+			"Unsupported size of TX queue: %d is not a power of 2.\n",
 			nb_desc);
 		return -EINVAL;
 	}
@@ -1337,7 +1337,7 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev,
 
 	if (!rte_is_power_of_2(nb_desc)) {
 		RTE_LOG(ERR, PMD,
-			"Unsupported size of RX queue: %d is not a power of 2.",
+			"Unsupported size of RX queue: %d is not a power of 2.\n",
 			nb_desc);
 		return -EINVAL;
 	}
@@ -1410,7 +1410,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count)
 		return 0;
 
 	in_use = rxq->next_to_use - rxq->next_to_clean;
-	ena_assert_msg(((in_use + count) < ring_size), "bad ring state");
+	ena_assert_msg(((in_use + count) < ring_size), "bad ring state\n");
 
 	/* get resources for incoming packets */
 	rc = rte_mempool_get_bulk(rxq->mb_pool, (void **)mbufs, count);
@@ -1643,7 +1643,7 @@ ena_set_queues_placement_policy(struct ena_adapter *adapter,
 	rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations);
 	if (unlikely(rc)) {
 		PMD_INIT_LOG(WARNING, "Failed to config dev mode. "
-			"Fallback to host mode policy.\n");
+			"Fallback to host mode policy.");
 		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
 		return 0;
 	}
@@ -1945,12 +1945,12 @@ static void ena_infos_get(struct rte_eth_dev *dev,
 	uint64_t rx_feat = 0, tx_feat = 0;
 	int rc = 0;
 
-	ena_assert_msg(dev->data != NULL, "Uninitialized device");
-	ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device");
+	ena_assert_msg(dev->data != NULL, "Uninitialized device\n");
+	ena_assert_msg(dev->data->dev_private != NULL, "Uninitialized device\n");
 	adapter = (struct ena_adapter *)(dev->data->dev_private);
 
 	ena_dev = &adapter->ena_dev;
-	ena_assert_msg(ena_dev != NULL, "Uninitialized device");
+	ena_assert_msg(ena_dev != NULL, "Uninitialized device\n");
 
 	dev_info->speed_capa =
 			ETH_LINK_SPEED_1G   |
Signature · 1 line
2.14.1
#12 lore raw

PATCH 12/20 net/ena: add supported RSS offloads types

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

The PMD was not passing RSS offloads values although it was supporting the RSS. To allow application to probe the PMD for RSS support, the missing information was added.

Fixes 1173fca25af9 ("ena: add polling-mode driver")
---
 drivers/net/ena/ena_ethdev.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/net/ena/ena_ethdev.c +3 -0
index 5adc87355..3aa32a3bf 100644
@@ -1994,6 +1994,9 @@ static void ena_infos_get(struct rte_eth_dev *dev,
 	dev_info->tx_offload_capa = tx_feat;
 	dev_info->tx_queue_offload_capa = tx_feat;
 
+	dev_info->flow_type_rss_offloads = ETH_RSS_IP | ETH_RSS_TCP |
+					   ETH_RSS_UDP;
+
 	dev_info->min_rx_bufsize = ENA_MIN_FRAME_LEN;
 	dev_info->max_rx_pktlen  = adapter->max_mtu;
 	dev_info->max_mac_addrs = 1;
Signature · 1 line
2.14.1
#13 lore raw

PATCH 13/20 net/ena: fix invalid reference to variable in union

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

Use empty_rx_reqs instead of empty_tx_reqs.
As those two variables are part of union this not cause any failure, but for consistency should be changed.

Fixes c2034976673d ("net/ena: add Rx out of order completion")
---
 drivers/net/ena/ena_ethdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ena/ena_ethdev.c +1 -1
index 3aa32a3bf..14165561e 100644
@@ -1387,7 +1387,7 @@ static int ena_rx_queue_setup(struct rte_eth_dev *dev,
 	}
 
 	for (i = 0; i < nb_desc; i++)
-		rxq->empty_tx_reqs[i] = i;
+		rxq->empty_rx_reqs[i] = i;
 
 	/* Store pointer to this queue in upper layer */
 	rxq->configured = 1;
Signature · 1 line
2.14.1
#14 lore raw

PATCH 14/20 net/ena: fix cleanup for out of order packets

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

When wrong req_id is detected some previous mbufs could be used for receiving different segments of received packets. In such cases chained mbufs will be twice returned to pool.

To prevent it chained mbuf is now freed just after error detection.

To simplify cleaning, pointers taken for Rx ring are set to NULL.

As after ena_rx_queue_release_bufs and ena_tx_queue_release_bufs queues are not used updating of next_to_clean pointer is not necessary.

Fixes c2034976673d ("net/ena: add Rx out of order completion")
---
 drivers/net/ena/ena_ethdev.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)
drivers/net/ena/ena_ethdev.c +10 -14
index 14165561e..ce0ca40c4 100644
@@ -770,17 +770,11 @@ static void ena_tx_queue_release(void *queue)
 
 static void ena_rx_queue_release_bufs(struct ena_ring *ring)
 {
-	unsigned int ring_mask = ring->ring_size - 1;
-
-	while (ring->next_to_clean != ring->next_to_use) {
-		struct rte_mbuf *m =
-			ring->rx_buffer_info[ring->next_to_clean & ring_mask];
-
-		if (m)
-			rte_mbuf_raw_free(m);
-
-		ring->next_to_clean++;
-	}
+	for (unsigned int i = 0; i < ring->ring_size; ++i)
+		if (ring->rx_buffer_info[i]) {
+			rte_mbuf_raw_free(ring->rx_buffer_info[i]);
+			ring->rx_buffer_info[i] = NULL;
+		}
 }
 
 static void ena_tx_queue_release_bufs(struct ena_ring *ring)
@@ -792,8 +786,6 @@ static void ena_tx_queue_release_bufs(struct ena_ring *ring)
 
 		if (tx_buf->mbuf)
 			rte_pktmbuf_free(tx_buf->mbuf);
-
-		ring->next_to_clean++;
 	}
 }
 
@@ -2077,10 +2069,14 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		while (segments < ena_rx_ctx.descs) {
 			req_id = ena_rx_ctx.ena_bufs[segments].req_id;
 			rc = validate_rx_req_id(rx_ring, req_id);
-			if (unlikely(rc))
+			if (unlikely(rc)) {
+				if (segments != 0)
+					rte_mbuf_raw_free(mbuf_head);
 				break;
+			}
 
 			mbuf = rx_buff_info[req_id];
+			rx_buff_info[req_id] = NULL;
 			mbuf->data_len = ena_rx_ctx.ena_bufs[segments].len;
 			mbuf->data_off = RTE_PKTMBUF_HEADROOM;
 			mbuf->refcnt = 1;
Signature · 1 line
2.14.1
#15 lore raw

PATCH 15/20 net/ena: add per-queue software counters stats

In reply to Michal Krawczyk

Those counters provide information regards sent/received bytes and packets per queue.

---
 drivers/net/ena/ena_ethdev.c | 36 +++++++++++++++++++++++++-
 drivers/net/ena/ena_ethdev.h | 60 ++++++++++++++++++++++++--------------------
 2 files changed, 68 insertions(+), 28 deletions(-)
drivers/net/ena/ena_ethdev.c +35 -1
index ce0ca40c4..799dcefcd 100644
@@ -160,6 +160,7 @@ static const struct ena_stats ena_stats_rx_strings[] = {
 	ENA_STAT_RX_ENTRY(dma_mapping_err),
 	ENA_STAT_RX_ENTRY(bad_desc_num),
 	ENA_STAT_RX_ENTRY(small_copy_len_pkt),
+	ENA_STAT_TX_ENTRY(bad_req_id),
 };
 
 static const struct ena_stats ena_stats_ena_com_strings[] = {
@@ -390,6 +391,7 @@ static inline int validate_rx_req_id(struct ena_ring *rx_ring, uint16_t req_id)
 
 	rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
 	rx_ring->adapter->trigger_reset = true;
+	++rx_ring->rx_stats.bad_req_id;
 
 	return -EFAULT;
 }
@@ -969,6 +971,8 @@ static int ena_stats_get(struct rte_eth_dev *dev,
 		(struct ena_adapter *)(dev->data->dev_private);
 	struct ena_com_dev *ena_dev = &adapter->ena_dev;
 	int rc;
+	int i;
+	int max_rings_stats;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return -ENOTSUP;
@@ -996,6 +1000,27 @@ static int ena_stats_get(struct rte_eth_dev *dev,
 	stats->ierrors = rte_atomic64_read(&adapter->drv_stats->ierrors);
 	stats->oerrors = rte_atomic64_read(&adapter->drv_stats->oerrors);
 	stats->rx_nombuf = rte_atomic64_read(&adapter->drv_stats->rx_nombuf);
+
+	max_rings_stats = RTE_MIN(dev->data->nb_rx_queues,
+		RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (i = 0; i < max_rings_stats; ++i) {
+		struct ena_stats_rx *rx_stats = &adapter->rx_ring[i].rx_stats;
+
+		stats->q_ibytes[i] = rx_stats->bytes;
+		stats->q_ipackets[i] = rx_stats->cnt;
+		stats->q_errors[i] = rx_stats->bad_desc_num +
+			rx_stats->bad_req_id;
+	}
+
+	max_rings_stats = RTE_MIN(dev->data->nb_tx_queues,
+		RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (i = 0; i < max_rings_stats; ++i) {
+		struct ena_stats_tx *tx_stats = &adapter->tx_ring[i].tx_stats;
+
+		stats->q_obytes[i] = tx_stats->bytes;
+		stats->q_opackets[i] = tx_stats->cnt;
+	}
+
 	return 0;
 }
 
@@ -1408,6 +1433,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count)
 	rc = rte_mempool_get_bulk(rxq->mb_pool, (void **)mbufs, count);
 	if (unlikely(rc < 0)) {
 		rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf);
+		++rxq->rx_stats.page_alloc_fail;
 		PMD_RX_LOG(DEBUG, "there are no enough free buffers");
 		return 0;
 	}
@@ -2108,8 +2134,10 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		/* pass to DPDK application head mbuf */
 		rx_pkts[recv_idx] = mbuf_head;
 		recv_idx++;
+		rx_ring->rx_stats.bytes += mbuf_head->pkt_len;
 	}
 
+	rx_ring->rx_stats.cnt += recv_idx;
 	rx_ring->next_to_clean = next_to_clean;
 
 	desc_in_use = desc_in_use - completed + 1;
@@ -2256,6 +2284,7 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 	uint16_t push_len = 0;
 	uint16_t delta = 0;
 	int nb_hw_desc;
+	uint32_t total_length;
 
 	/* Check adapter state */
 	if (unlikely(tx_ring->adapter->state != ENA_ADAPTER_STATE_RUNNING)) {
@@ -2270,6 +2299,7 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	for (sent_idx = 0; sent_idx < nb_pkts; sent_idx++) {
 		mbuf = tx_pkts[sent_idx];
+		total_length = 0;
 
 		rc = ena_check_and_linearize_mbuf(tx_ring, mbuf);
 		if (unlikely(rc))
@@ -2335,6 +2365,7 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 			ebuf++;
 			tx_info->num_of_bufs++;
 		}
+		total_length += mbuf->data_len;
 
 		while ((mbuf = mbuf->next) != NULL) {
 			seg_len = mbuf->data_len;
@@ -2347,6 +2378,7 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 			ebuf->paddr = mbuf->buf_iova + mbuf->data_off + delta;
 			ebuf->len = seg_len - delta;
+			total_length += ebuf->len;
 			ebuf++;
 			tx_info->num_of_bufs++;
 
@@ -2373,6 +2405,8 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		tx_info->tx_descs = nb_hw_desc;
 
 		next_to_use++;
+		tx_ring->tx_stats.cnt += tx_info->num_of_bufs;
+		tx_ring->tx_stats.bytes += total_length;
 	}
 
 	/* If there are ready packets to be xmitted... */
@@ -2380,7 +2414,7 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		/* ...let HW do its best :-) */
 		rte_wmb();
 		ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq);
-
+		tx_ring->tx_stats.doorbells++;
 		tx_ring->next_to_use = next_to_use;
 	}
 
drivers/net/ena/ena_ethdev.h +33 -27

78 lines not on this page · raw message

Signature · 1 line
2.14.1
#16 lore raw

PATCH 16/20 net/ena: expose ENA-specific statistics in extended stats

In reply to Michal Krawczyk

From: Solganik Alexander <[email protected]>

ENA PMD is having it's own custom statistics counters. They are exposed to the application by using the xstats DPDK API.

The deprecated and unused statistics are removed, together with old API.

---
 drivers/net/ena/ena_ethdev.c | 274 +++++++++++++++++++++++++++++++++----------
 drivers/net/ena/ena_ethdev.h |  22 ++--
 2 files changed, 220 insertions(+), 76 deletions(-)
drivers/net/ena/ena_ethdev.c +213 -61
index 799dcefcd..c3a26d402 100644
@@ -80,7 +80,6 @@
 #define ENA_RX_RSS_TABLE_LOG_SIZE  7
 #define ENA_RX_RSS_TABLE_SIZE	(1 << ENA_RX_RSS_TABLE_LOG_SIZE)
 #define ENA_HASH_KEY_SIZE	40
-#define ENA_ETH_SS_STATS	0xFF
 #define ETH_GSTRING_LEN	32
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -97,11 +96,6 @@ struct ena_stats {
 	int stat_offset;
 };
 
-#define ENA_STAT_ENA_COM_ENTRY(stat) { \
-	.name = #stat, \
-	.stat_offset = offsetof(struct ena_com_stats_admin, stat) \
-}
-
 #define ENA_STAT_ENTRY(stat, stat_type) { \
 	.name = #stat, \
 	.stat_offset = offsetof(struct ena_stats_##stat_type, stat) \
@@ -126,55 +120,36 @@ struct ena_stats {
 uint32_t ena_alloc_cnt;
 
 static const struct ena_stats ena_stats_global_strings[] = {
-	ENA_STAT_GLOBAL_ENTRY(tx_timeout),
-	ENA_STAT_GLOBAL_ENTRY(io_suspend),
-	ENA_STAT_GLOBAL_ENTRY(io_resume),
 	ENA_STAT_GLOBAL_ENTRY(wd_expired),
-	ENA_STAT_GLOBAL_ENTRY(interface_up),
-	ENA_STAT_GLOBAL_ENTRY(interface_down),
-	ENA_STAT_GLOBAL_ENTRY(admin_q_pause),
+	ENA_STAT_GLOBAL_ENTRY(dev_start),
+	ENA_STAT_GLOBAL_ENTRY(dev_stop),
 };
 
 static const struct ena_stats ena_stats_tx_strings[] = {
 	ENA_STAT_TX_ENTRY(cnt),
 	ENA_STAT_TX_ENTRY(bytes),
-	ENA_STAT_TX_ENTRY(queue_stop),
-	ENA_STAT_TX_ENTRY(queue_wakeup),
-	ENA_STAT_TX_ENTRY(dma_mapping_err),
+	ENA_STAT_TX_ENTRY(prepare_ctx_err),
 	ENA_STAT_TX_ENTRY(linearize),
 	ENA_STAT_TX_ENTRY(linearize_failed),
 	ENA_STAT_TX_ENTRY(tx_poll),
 	ENA_STAT_TX_ENTRY(doorbells),
-	ENA_STAT_TX_ENTRY(prepare_ctx_err),
-	ENA_STAT_TX_ENTRY(missing_tx_comp),
 	ENA_STAT_TX_ENTRY(bad_req_id),
+	ENA_STAT_TX_ENTRY(available_desc),
 };
 
 static const struct ena_stats ena_stats_rx_strings[] = {
 	ENA_STAT_RX_ENTRY(cnt),
 	ENA_STAT_RX_ENTRY(bytes),
-	ENA_STAT_RX_ENTRY(refil_partial),
+	ENA_STAT_RX_ENTRY(refill_partial),
 	ENA_STAT_RX_ENTRY(bad_csum),
-	ENA_STAT_RX_ENTRY(page_alloc_fail),
-	ENA_STAT_RX_ENTRY(skb_alloc_fail),
-	ENA_STAT_RX_ENTRY(dma_mapping_err),
+	ENA_STAT_RX_ENTRY(mbuf_alloc_fail),
 	ENA_STAT_RX_ENTRY(bad_desc_num),
-	ENA_STAT_RX_ENTRY(small_copy_len_pkt),
-	ENA_STAT_TX_ENTRY(bad_req_id),
-};
-
-static const struct ena_stats ena_stats_ena_com_strings[] = {
-	ENA_STAT_ENA_COM_ENTRY(aborted_cmd),
-	ENA_STAT_ENA_COM_ENTRY(submitted_cmd),
-	ENA_STAT_ENA_COM_ENTRY(completed_cmd),
-	ENA_STAT_ENA_COM_ENTRY(out_of_space),
-	ENA_STAT_ENA_COM_ENTRY(no_completion),
+	ENA_STAT_RX_ENTRY(bad_req_id),
 };
 
 #define ENA_STATS_ARRAY_GLOBAL	ARRAY_SIZE(ena_stats_global_strings)
 #define ENA_STATS_ARRAY_TX	ARRAY_SIZE(ena_stats_tx_strings)
 #define ENA_STATS_ARRAY_RX	ARRAY_SIZE(ena_stats_rx_strings)
-#define ENA_STATS_ARRAY_ENA_COM	ARRAY_SIZE(ena_stats_ena_com_strings)
 
 #define QUEUE_OFFLOADS (DEV_TX_OFFLOAD_TCP_CKSUM |\
 			DEV_TX_OFFLOAD_UDP_CKSUM |\
@@ -260,11 +235,20 @@ static int ena_rss_reta_update(struct rte_eth_dev *dev,
 static int ena_rss_reta_query(struct rte_eth_dev *dev,
 			      struct rte_eth_rss_reta_entry64 *reta_conf,
 			      uint16_t reta_size);
-static int ena_get_sset_count(struct rte_eth_dev *dev, int sset);
 static void ena_interrupt_handler_rte(void *cb_arg);
 static void ena_timer_wd_callback(struct rte_timer *timer, void *arg);
 static void ena_destroy_device(struct rte_eth_dev *eth_dev);
 static int eth_ena_dev_init(struct rte_eth_dev *eth_dev);
+static int ena_xstats_get_names(struct rte_eth_dev *dev,
+				struct rte_eth_xstat_name *xstats_names,
+				unsigned int n);
+static int ena_xstats_get(struct rte_eth_dev *dev,
+			  struct rte_eth_xstat *stats,
+			  unsigned int n);
+static int ena_xstats_get_by_id(struct rte_eth_dev *dev,
+				const uint64_t *ids,
+				uint64_t *values,
+				unsigned int n);
 
 static const struct eth_dev_ops ena_dev_ops = {
 	.dev_configure        = ena_dev_configure,
@@ -275,6 +259,9 @@ static const struct eth_dev_ops ena_dev_ops = {
 	.dev_stop             = ena_stop,
 	.link_update          = ena_link_update,
 	.stats_get            = ena_stats_get,
+	.xstats_get_names     = ena_xstats_get_names,
+	.xstats_get	      = ena_xstats_get,
+	.xstats_get_by_id     = ena_xstats_get_by_id,
 	.mtu_set              = ena_mtu_set,
 	.rx_queue_release     = ena_rx_queue_release,
 	.tx_queue_release     = ena_tx_queue_release,
@@ -412,6 +399,7 @@ static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id)
 		RTE_LOG(ERR, PMD, "Invalid req_id: %hu\n", req_id);
 
 	/* Trigger device reset */
+	++tx_ring->tx_stats.bad_req_id;
 	tx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_TX_REQ_ID;
 	tx_ring->adapter->trigger_reset	= true;
 	return -EFAULT;
@@ -463,24 +451,12 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev)
 	ena_com_delete_host_info(ena_dev);
 }
 
-static int
-ena_get_sset_count(struct rte_eth_dev *dev, int sset)
+/* This function calculates the number of xstats based on the current config */
+static unsigned int ena_xstats_calc_num(struct rte_eth_dev *dev)
 {
-	if (sset != ETH_SS_STATS)
-		return -EOPNOTSUPP;
-
-	 /* Workaround for clang:
-	 * touch internal structures to prevent
-	 * compiler error
-	 */
-	ENA_TOUCH(ena_stats_global_strings);
-	ENA_TOUCH(ena_stats_tx_strings);
-	ENA_TOUCH(ena_stats_rx_strings);
-	ENA_TOUCH(ena_stats_ena_com_strings);
-
-	return  dev->data->nb_tx_queues *
-		(ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) +
-		ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
+	return ENA_STATS_ARRAY_GLOBAL +
+		(dev->data->nb_tx_queues * ENA_STATS_ARRAY_TX) +
+		(dev->data->nb_rx_queues * ENA_STATS_ARRAY_RX);
 }
 
 static void ena_config_debug_area(struct ena_adapter *adapter)
@@ -488,11 +464,7 @@ static void ena_config_debug_area(struct ena_adapter *adapter)
 	u32 debug_area_size;
 	int rc, ss_count;
 
-	ss_count = ena_get_sset_count(adapter->rte_dev, ETH_SS_STATS);
-	if (ss_count <= 0) {
-		RTE_LOG(ERR, PMD, "SS count is negative\n");
-		return;
-	}
+	ss_count = ena_xstats_calc_num(adapter->rte_dev);
 
 	/* allocate 32 bytes for each string and 64bit for the value */
 	debug_area_size = ss_count * ETH_GSTRING_LEN + sizeof(u64) * ss_count;
@@ -1089,6 +1061,7 @@ static int ena_start(struct rte_eth_dev *dev)
 	rte_timer_reset(&adapter->timer_wd, ticks, PERIODICAL, rte_lcore_id(),
 			ena_timer_wd_callback, adapter);
 
+	++adapter->dev_stats.dev_start;
 	adapter->state = ENA_ADAPTER_STATE_RUNNING;
 
 	return 0;
@@ -1117,6 +1090,7 @@ static void ena_stop(struct rte_eth_dev *dev)
 			RTE_LOG(ERR, PMD, "Device reset failed rc=%d\n", rc);
 	}
 
+	++adapter->dev_stats.dev_stop;
 	adapter->state = ENA_ADAPTER_STATE_STOPPED;
 }
 
@@ -1228,8 +1202,11 @@ static int ena_queue_start(struct ena_ring *ring)
 	ring->next_to_clean = 0;
 	ring->next_to_use = 0;
 
-	if (ring->type == ENA_RING_TYPE_TX)
+	if (ring->type == ENA_RING_TYPE_TX) {
+		ring->tx_stats.available_desc =
+			ena_com_free_desc(ring->ena_com_io_sq);
 		return 0;
+	}
 
 	bufs_num = ring->ring_size - 1;
 	rc = ena_populate_rx_queue(ring, bufs_num);
@@ -1321,7 +1298,6 @@ static int ena_tx_queue_setup(struct rte_eth_dev *dev,
 		txq->offloads =
 			tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
 	}
-
 	/* Store pointer to this queue in upper layer */
 	txq->configured = 1;
 	dev->data->tx_queues[queue_idx] = txq;
@@ -1433,7 +1409,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count)
 	rc = rte_mempool_get_bulk(rxq->mb_pool, (void **)mbufs, count);
 	if (unlikely(rc < 0)) {
 		rte_atomic64_inc(&rxq->adapter->drv_stats->rx_nombuf);
-		++rxq->rx_stats.page_alloc_fail;
+		++rxq->rx_stats.mbuf_alloc_fail;
 		PMD_RX_LOG(DEBUG, "there are no enough free buffers");
 		return 0;
 	}
@@ -1471,6 +1447,7 @@ static int ena_populate_rx_queue(struct ena_ring *rxq, unsigned int count)
 			"buffers (from %d)\n", rxq->id, i, count);
 		rte_mempool_put_bulk(rxq->mb_pool, (void **)(&mbufs[i]),
 				     count - i);
+		++rxq->rx_stats.refill_partial;
 	}
 
 	/* When we submitted free recources to device... */
@@ -1601,6 +1578,7 @@ static void check_for_missing_keep_alive(struct ena_adapter *adapter)
 		RTE_LOG(ERR, PMD, "Keep alive timeout\n");
 		adapter->reset_reason = ENA_REGS_RESET_KEEP_ALIVE_TO;
 		adapter->trigger_reset = true;
+		++adapter->dev_stats.wd_expired;
 	}
 }
 
@@ -2086,6 +2064,7 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			rx_ring->adapter->reset_reason =
 				ENA_REGS_RESET_TOO_MANY_RX_DESCS;
 			rx_ring->adapter->trigger_reset = true;
+			++rx_ring->rx_stats.bad_desc_num;
 			return 0;
 		}
 
@@ -2129,6 +2108,11 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 		/* fill mbuf attributes if any */
 		ena_rx_mbuf_prepare(mbuf_head, &ena_rx_ctx);
+
+		if (unlikely(mbuf_head->ol_flags &
+			(PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD)))
+			++rx_ring->rx_stats.bad_csum;
+
 		mbuf_head->hash.rss = ena_rx_ctx.hash;
 
 		/* pass to DPDK application head mbuf */
@@ -2259,9 +2243,14 @@ static int ena_check_and_linearize_mbuf(struct ena_ring *tx_ring,
 	    (header_len < tx_ring->tx_max_header_size))
 		return 0;
 
+	++tx_ring->tx_stats.linearize;
 	rc = rte_pktmbuf_linearize(mbuf);
-	if (unlikely(rc))
+	if (unlikely(rc)) {
 		RTE_LOG(WARNING, PMD, "Mbuf linearize failed\n");
+		rte_atomic64_inc(&tx_ring->adapter->drv_stats->ierrors);
+		++tx_ring->tx_stats.linearize_failed;
+		return rc;
+	}
 
 	return rc;
 }
@@ -2399,15 +2388,18 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		/* prepare the packet's descriptors to dma engine */
 		rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq,
 					&ena_tx_ctx, &nb_hw_desc);
-		if (unlikely(rc))
+		if (unlikely(rc)) {
+			++tx_ring->tx_stats.prepare_ctx_err;
 			break;
-
+		}
 		tx_info->tx_descs = nb_hw_desc;
 
 		next_to_use++;
 		tx_ring->tx_stats.cnt += tx_info->num_of_bufs;
 		tx_ring->tx_stats.bytes += total_length;
 	}
+	tx_ring->tx_stats.available_desc =
+		ena_com_free_desc(tx_ring->ena_com_io_sq);
 
 	/* If there are ready packets to be xmitted... */
 	if (sent_idx > 0) {
@@ -2441,6 +2433,8 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		if (unlikely(total_tx_descs > ENA_RING_DESCS_RATIO(ring_size)))
 			break;
 	}
+	tx_ring->tx_stats.available_desc =
+		ena_com_free_desc(tx_ring->ena_com_io_sq);
 
 	if (total_tx_descs > 0) {
 		/* acknowledge completion of sent packets */
@@ -2448,9 +2442,167 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		tx_ring->next_to_clean = next_to_clean;
 	}
 
+	tx_ring->tx_stats.tx_poll++;
+
 	return sent_idx;
 }
 
+/**
+ * DPDK callback to retrieve names of extended device statistics
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param[out] xstats_names
+ *   Buffer to insert names into.
+ * @param n
+ *   Number of names.
+ *
+ * @return
+ *   Number of xstats names.
+ */
+static int ena_xstats_get_names(struct rte_eth_dev *dev,
+				struct rte_eth_xstat_name *xstats_names,
+				unsigned int n)
+{
+	unsigned int xstats_count = ena_xstats_calc_num(dev);
+	unsigned int stat, i, count = 0;
+
+	if (n < xstats_count || !xstats_names)
+		return xstats_count;
+
+	for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++)
+		strcpy(xstats_names[count].name,
+			ena_stats_global_strings[stat].name);
+
+	for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++)
+		for (i = 0; i < dev->data->nb_rx_queues; i++, count++)
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"rx_q%d_%s", i,
+				ena_stats_rx_strings[stat].name);
+
+	for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++)
+		for (i = 0; i < dev->data->nb_tx_queues; i++, count++)
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"tx_q%d_%s", i,
+				ena_stats_tx_strings[stat].name);
+
+	return xstats_count;
+}
+
+/**
+ * DPDK callback to get extended device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param[out] stats
+ *   Stats table output buffer.
+ * @param n
+ *   The size of the stats table.
+ *
+ * @return
+ *   Number of xstats on success, negative on failure.
+ */
+static int ena_xstats_get(struct rte_eth_dev *dev,
+			  struct rte_eth_xstat *xstats,
+			  unsigned int n)
+{
+	struct ena_adapter *adapter =
+			(struct ena_adapter *)(dev->data->dev_private);
+	unsigned int xstats_count = ena_xstats_calc_num(dev);
+	unsigned int stat, i, count = 0;
+	int stat_offset;
+	void *stats_begin;
+
+	if (n < xstats_count)
+		return xstats_count;
+
+	if (!xstats)
+		return 0;
+
+	for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) {
+		stat_offset = ena_stats_rx_strings[stat].stat_offset;
+		stats_begin = &adapter->dev_stats;
+
+		xstats[count].id = count;
+		xstats[count].value = *((uint64_t *)
+			((char *)stats_begin + stat_offset));
+	}
+
+	for (stat = 0; stat < ENA_STATS_ARRAY_RX; stat++) {
+		for (i = 0; i < dev->data->nb_rx_queues; i++, count++) {
+			stat_offset = ena_stats_rx_strings[stat].stat_offset;
+			stats_begin = &adapter->rx_ring[i].rx_stats;
+
+			xstats[count].id = count;
+			xstats[count].value = *((uint64_t *)
+				((char *)stats_begin + stat_offset));
+		}
+	}
+
+	for (stat = 0; stat < ENA_STATS_ARRAY_TX; stat++) {
+		for (i = 0; i < dev->data->nb_tx_queues; i++, count++) {
+			stat_offset = ena_stats_tx_strings[stat].stat_offset;
+			stats_begin = &adapter->tx_ring[i].rx_stats;
+
+			xstats[count].id = count;
+			xstats[count].value = *((uint64_t *)
+				((char *)stats_begin + stat_offset));
+		}
+	}
+
+	return count;
+}
+
+static int ena_xstats_get_by_id(struct rte_eth_dev *dev,
+				const uint64_t *ids,
+				uint64_t *values,
+				unsigned int n)
+{
+	struct ena_adapter *adapter =
+		(struct ena_adapter *)(dev->data->dev_private);
+	uint64_t id;
+	uint64_t rx_entries, tx_entries;
+	unsigned int i;
+	int qid;
+	int valid = 0;
+	for (i = 0; i < n; ++i) {
+		id = ids[i];
+		/* Check if id belongs to global statistics */
+		if (id < ENA_STATS_ARRAY_GLOBAL) {
+			values[i] = *((uint64_t *)&adapter->dev_stats + id);
+			++valid;
+			continue;
+		}
+
+		/* Check if id belongs to rx queue statistics */
+		id -= ENA_STATS_ARRAY_GLOBAL;
+		rx_entries = ENA_STATS_ARRAY_RX * dev->data->nb_rx_queues;
+		if (id < rx_entries) {
+			qid = id % dev->data->nb_rx_queues;
+			id /= dev->data->nb_rx_queues;
+			values[i] = *((uint64_t *)
+				&adapter->rx_ring[qid].rx_stats + id);
+			++valid;
+			continue;
+		}
+				/* Check if id belongs to rx queue statistics */
+		id -= rx_entries;
+		tx_entries = ENA_STATS_ARRAY_TX * dev->data->nb_tx_queues;
+		if (id < tx_entries) {
+			qid = id % dev->data->nb_tx_queues;
+			id /= dev->data->nb_tx_queues;
+			values[i] = *((uint64_t *)
+				&adapter->tx_ring[qid].tx_stats + id);
+			++valid;
+			continue;
+		}
+	}
+
+	return valid;
+}
+
 /*********************************************************************
  *  PMD configuration
  *********************************************************************/
drivers/net/ena/ena_ethdev.h +7 -15
index 255e1c0ec..9eca6e63b 100644
@@ -82,28 +82,22 @@ struct ena_calc_queue_size_ctx {
 struct ena_stats_tx {
 	u64 cnt;
 	u64 bytes;
-	u64 queue_stop;
 	u64 prepare_ctx_err;
-	u64 queue_wakeup;
-	u64 dma_mapping_err;
 	u64 linearize;
 	u64 linearize_failed;
 	u64 tx_poll;
 	u64 doorbells;
-	u64 missing_tx_comp;
 	u64 bad_req_id;
+	u64 available_desc;
 };
 
 struct ena_stats_rx {
 	u64 cnt;
 	u64 bytes;
-	u64 refil_partial;
+	u64 refill_partial;
 	u64 bad_csum;
-	u64 page_alloc_fail;
-	u64 skb_alloc_fail;
-	u64 dma_mapping_err;
+	u64 mbuf_alloc_fail;
 	u64 bad_desc_num;
-	u64 small_copy_len_pkt;
 	u64 bad_req_id;
 };
 
@@ -167,13 +161,9 @@ struct ena_driver_stats {
 };
 
 struct ena_stats_dev {
-	u64 tx_timeout;
-	u64 io_suspend;
-	u64 io_resume;
 	u64 wd_expired;
-	u64 interface_up;
-	u64 interface_down;
-	u64 admin_q_pause;
+	u64 dev_start;
+	u64 dev_stop;
 };
 
 /* board specific private data structure */
@@ -222,6 +212,8 @@ struct ena_adapter {
 	uint64_t timestamp_wd;
 	uint64_t keep_alive_timeout;
 
+	struct ena_stats_dev dev_stats;
+
 	bool trigger_reset;
 
 	bool wd_state;
Signature · 1 line
2.14.1
#17 lore raw

PATCH 17/20 net/ena: new way of getting rx drops

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

The Rx drops cannot be acquired using the older API. Now, it must be read in keep alive message.

---
 drivers/net/ena/ena_ethdev.c | 10 ++++++++--
 drivers/net/ena/ena_ethdev.h |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)
drivers/net/ena/ena_ethdev.c +8 -2
index c3a26d402..2b84cc79d 100644
@@ -933,6 +933,7 @@ static void ena_stats_restart(struct rte_eth_dev *dev)
 	rte_atomic64_init(&adapter->drv_stats->ierrors);
 	rte_atomic64_init(&adapter->drv_stats->oerrors);
 	rte_atomic64_init(&adapter->drv_stats->rx_nombuf);
+	rte_atomic64_init(&adapter->drv_stats->rx_drops);
 }
 
 static int ena_stats_get(struct rte_eth_dev *dev,
@@ -965,10 +966,9 @@ static int ena_stats_get(struct rte_eth_dev *dev,
 					ena_stats.rx_bytes_low);
 	stats->obytes = __MERGE_64B_H_L(ena_stats.tx_bytes_high,
 					ena_stats.tx_bytes_low);
-	stats->imissed = __MERGE_64B_H_L(ena_stats.rx_drops_high,
-					 ena_stats.rx_drops_low);
 
 	/* Driver related stats */
+	stats->imissed = rte_atomic64_read(&adapter->drv_stats->rx_drops);
 	stats->ierrors = rte_atomic64_read(&adapter->drv_stats->ierrors);
 	stats->oerrors = rte_atomic64_read(&adapter->drv_stats->oerrors);
 	stats->rx_nombuf = rte_atomic64_read(&adapter->drv_stats->rx_nombuf);
@@ -2689,8 +2689,14 @@ static void ena_keep_alive(void *adapter_data,
 			   __rte_unused struct ena_admin_aenq_entry *aenq_e)
 {
 	struct ena_adapter *adapter = (struct ena_adapter *)adapter_data;
+	struct ena_admin_aenq_keep_alive_desc *desc;
+	uint64_t rx_drops;
 
 	adapter->timestamp_wd = rte_get_timer_cycles();
+
+	desc = (struct ena_admin_aenq_keep_alive_desc *)aenq_e;
+	rx_drops = ((uint64_t)desc->rx_drops_high << 32) | desc->rx_drops_low;
+	rte_atomic64_set(&adapter->drv_stats->rx_drops, rx_drops);
 }
 
 /**
drivers/net/ena/ena_ethdev.h +1 -0
index 9eca6e63b..309b92f65 100644
@@ -158,6 +158,7 @@ struct ena_driver_stats {
 	rte_atomic64_t ierrors;
 	rte_atomic64_t oerrors;
 	rte_atomic64_t rx_nombuf;
+	rte_atomic64_t rx_drops;
 };
 
 struct ena_stats_dev {
Signature · 1 line
2.14.1
#18 lore raw

PATCH 18/20 net/ena: update completion queue after cleanup

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

After Rx or Tx cleanup update completion queue head by calling ena_com_update_dev_comp_head().

Fixes 1daff5260ff8 ("net/ena: use unmasked head and tail")
---
 drivers/net/ena/ena_ethdev.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/net/ena/ena_ethdev.c +5 -2
index 2b84cc79d..b336102ba 100644
@@ -2126,8 +2126,10 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 
 	desc_in_use = desc_in_use - completed + 1;
 	/* Burst refill to save doorbells, memory barriers, const interval */
-	if (ring_size - desc_in_use > ENA_RING_DESCS_RATIO(ring_size))
+	if (ring_size - desc_in_use > ENA_RING_DESCS_RATIO(ring_size)) {
+		ena_com_update_dev_comp_head(rx_ring->ena_com_io_cq);
 		ena_populate_rx_queue(rx_ring, ring_size - desc_in_use);
+	}
 
 	return recv_idx;
 }
@@ -2438,8 +2440,9 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	if (total_tx_descs > 0) {
 		/* acknowledge completion of sent packets */
-		ena_com_comp_ack(tx_ring->ena_com_io_sq, total_tx_descs);
 		tx_ring->next_to_clean = next_to_clean;
+		ena_com_comp_ack(tx_ring->ena_com_io_sq, total_tx_descs);
+		ena_com_update_dev_comp_head(tx_ring->ena_com_io_cq);
 	}
 
 	tx_ring->tx_stats.tx_poll++;
Signature · 1 line
2.14.1
#19 lore raw

PATCH 19/20 docs: update ENA PMD documentation and features

In reply to Michal Krawczyk

Previously, the features list was indicating unsupported ENA PMD features and were missing few ones, that were actually supported.

The features file was updated, so it is now reflecting current driver state.

The documentation was updated with the more actual example and features, especially ones which are ENA and not listed in the features file.

---
 doc/guides/nics/ena.rst          | 31 ++++++++++++++++---------------
 doc/guides/nics/features/ena.ini | 12 ++++--------
 2 files changed, 20 insertions(+), 23 deletions(-)
doc/guides/nics/ena.rst +16 -15
index 34c48575b..9f0a6509f 100644
@@ -1,6 +1,6 @@
 .. BSD LICENSE
 
-    Copyright (c) 2015-2016 Amazon.com, Inc. or its affiliates.
+    Copyright (c) 2015-2018 Amazon.com, Inc. or its affiliates.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -164,20 +164,18 @@ section of :ref:`the DPDK documentation <linux_gsg>` or refer to *DPDK Release N
 Supported features
 ------------------
 
+* MTU configuration
 * Jumbo frames up to 9K
-* Port Hardware Statistics
 * IPv4/TCP/UDP checksum offload
 * TSO offload
 * Multiple receive and transmit queues
-* RSS
+* RSS hash
+* RSS indirection table configuration
 * Low Latency Queue for Tx
-
-Unsupported features
---------------------
-
-The features supported by the device and not yet supported by this PMD include:
-
-* Asynchronous Event Notification Queue (AENQ)
+* Basic and extended statistics
+* LSC event notification
+* Watchdog (requires handling of timers in the application)
+* Device reset upon failure
 
 Prerequisites
 -------------
@@ -214,14 +212,17 @@ Example output:
 .. code-block:: console
 
    [...]
-   EAL: PCI device 0000:02:00.1 on NUMA socket -1
-   EAL:   probe driver: 1d0f:ec20 rte_ena_pmd
-   EAL:   PCI memory mapped at 0x7f9b6c400000
-   PMD: eth_ena_dev_init(): Initializing 0:2:0.1
+   EAL: PCI device 0000:00:06.0 on NUMA socket -1
+   EAL:   Invalid NUMA socket, default to 0
+   EAL:   probe driver: 1d0f:ec20 net_ena
+
    Interactive-mode selected
+   testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=171456, size=2176, socket=0
+   testpmd: preferred mempool ops selected: ring_mp_mc
+   Warning! port-topology=paired and odd forward ports number, the last port will pair with itself.
    Configuring Port 0 (socket 0)
    Port 0: 00:00:00:11:00:01
    Checking link statuses...
-   Port 0 Link Up - speed 10000 Mbps - full-duplex
+
    Done
    testpmd>
doc/guides/nics/features/ena.ini +4 -8
index aa6f05a71..4300dd012 100644
@@ -4,25 +4,21 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
-Speed capabilities   = P
-Queue start/stop     = Y
+Link status          = Y
+Link status event    = Y
 MTU update           = Y
 Jumbo frame          = Y
 Scattered Rx         = Y
 TSO                  = Y
 RSS hash             = Y
-RSS key update       = Y
 RSS reta update      = Y
-SR-IOV               = Y
-CRC offload          = Y
-VLAN offload         = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
-Inner L3 checksum    = Y
-Inner L4 checksum    = Y
 Basic stats          = Y
 Extended stats       = Y
 Linux UIO            = Y
 Linux VFIO           = Y
 x86-32               = Y
 x86-64               = Y
+Usage doc            = Y
+Design doc           = Y
Signature · 1 line
2.14.1
#20 lore raw

PATCH 20/20 net/ena: release of the ENAv2 driver (v2.0.0)

In reply to Michal Krawczyk

The ENAv2 is introducing many new features, mainly the LLQ feature (Low Latency Queue) which allows the device to process packets faster and as a result, the latency is noticeably lower.

The second major feature is configurable depth of hw queues where Rx and Tx can be reconfigured independently and maximum depth of Rx queue is 8k.

The release also includes many bug fixes and minor new features, like improved statistics counters and extended statistics.

Driver is still compatible with ENAv1 device.

---
 drivers/net/ena/ena_ethdev.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ena/ena_ethdev.c +3 -3
index b336102ba..eba3e4c16 100644
@@ -53,9 +53,9 @@
 #include <ena_admin_defs.h>
 #include <ena_eth_io_defs.h>
 
-#define DRV_MODULE_VER_MAJOR	1
-#define DRV_MODULE_VER_MINOR	1
-#define DRV_MODULE_VER_SUBMINOR	1
+#define DRV_MODULE_VER_MAJOR	2
+#define DRV_MODULE_VER_MINOR	0
+#define DRV_MODULE_VER_SUBMINOR	0
 
 #define ENA_IO_TXQ_IDX(q)	(2 * (q))
 #define ENA_IO_RXQ_IDX(q)	(2 * (q) + 1)
Signature · 1 line
2.14.1
#21 lore raw

PATCH v2 14/20 net/ena: fix cleanup for out of order packets

In reply to Michal Krawczyk

From: Rafal Kozik <[email protected]>

When wrong req_id is detected some previous mbufs could be used for receiving different segments of received packets. In such cases chained mbufs will be twice returned to pool.

To prevent it chained mbuf is now freed just after error detection.

To simplify cleaning, pointers taken for Rx ring are set to NULL.

As after ena_rx_queue_release_bufs and ena_tx_queue_release_bufs queues are not used updating of next_to_clean pointer is not necessary.

Fixes c2034976673d ("net/ena: add Rx out of order completion")
Change-Id I5e93cfb93c145f507fee2a8b2fb230332ce78e33

---
v2:
* Fix for loop error when compiler is not using C99 mode

 drivers/net/ena/ena_ethdev.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
drivers/net/ena/ena_ethdev.c +11 -13
index 14165561e..364778840 100644
@@ -770,17 +770,13 @@ static void ena_tx_queue_release(void *queue)
 
 static void ena_rx_queue_release_bufs(struct ena_ring *ring)
 {
-	unsigned int ring_mask = ring->ring_size - 1;
-
-	while (ring->next_to_clean != ring->next_to_use) {
-		struct rte_mbuf *m =
-			ring->rx_buffer_info[ring->next_to_clean & ring_mask];
-
-		if (m)
-			rte_mbuf_raw_free(m);
+	unsigned int i;
 
-		ring->next_to_clean++;
-	}
+	for (i = 0; i < ring->ring_size; ++i)
+		if (ring->rx_buffer_info[i]) {
+			rte_mbuf_raw_free(ring->rx_buffer_info[i]);
+			ring->rx_buffer_info[i] = NULL;
+		}
 }
 
 static void ena_tx_queue_release_bufs(struct ena_ring *ring)
@@ -792,8 +788,6 @@ static void ena_tx_queue_release_bufs(struct ena_ring *ring)
 
 		if (tx_buf->mbuf)
 			rte_pktmbuf_free(tx_buf->mbuf);
-
-		ring->next_to_clean++;
 	}
 }
 
@@ -2077,10 +2071,14 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		while (segments < ena_rx_ctx.descs) {
 			req_id = ena_rx_ctx.ena_bufs[segments].req_id;
 			rc = validate_rx_req_id(rx_ring, req_id);
-			if (unlikely(rc))
+			if (unlikely(rc)) {
+				if (segments != 0)
+					rte_mbuf_raw_free(mbuf_head);
 				break;
+			}
 
 			mbuf = rx_buff_info[req_id];
+			rx_buff_info[req_id] = NULL;
 			mbuf->data_len = ena_rx_ctx.ena_bufs[segments].len;
 			mbuf->data_off = RTE_PKTMBUF_HEADROOM;
 			mbuf->refcnt = 1;
Signature · 1 line
2.14.1
#22 lore raw

PATCH v3 14/20 net/ena: fix cleanup for out of order packets

From: Rafal Kozik <[email protected]>

When wrong req_id is detected some previous mbufs could be used for receiving different segments of received packets. In such cases chained mbufs will be twice returned to pool.

To prevent it chained mbuf is now freed just after error detection.

To simplify cleaning, pointers taken for Rx ring are set to NULL.

As after ena_rx_queue_release_bufs and ena_tx_queue_release_bufs queues are not used updating of next_to_clean pointer is not necessary.

Fixes c2034976673d ("net/ena: add Rx out of order completion")

---
v3:
* Remove Gerrit Change-Id from commit message

v2:
* Fix for loop error when compiler is not using C99 mode

 drivers/net/ena/ena_ethdev.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
drivers/net/ena/ena_ethdev.c +11 -13
index 14165561e..364778840 100644
@@ -770,17 +770,13 @@ static void ena_tx_queue_release(void *queue)
 
 static void ena_rx_queue_release_bufs(struct ena_ring *ring)
 {
-	unsigned int ring_mask = ring->ring_size - 1;
-
-	while (ring->next_to_clean != ring->next_to_use) {
-		struct rte_mbuf *m =
-			ring->rx_buffer_info[ring->next_to_clean & ring_mask];
-
-		if (m)
-			rte_mbuf_raw_free(m);
+	unsigned int i;
 
-		ring->next_to_clean++;
-	}
+	for (i = 0; i < ring->ring_size; ++i)
+		if (ring->rx_buffer_info[i]) {
+			rte_mbuf_raw_free(ring->rx_buffer_info[i]);
+			ring->rx_buffer_info[i] = NULL;
+		}
 }
 
 static void ena_tx_queue_release_bufs(struct ena_ring *ring)
@@ -792,8 +788,6 @@ static void ena_tx_queue_release_bufs(struct ena_ring *ring)
 
 		if (tx_buf->mbuf)
 			rte_pktmbuf_free(tx_buf->mbuf);
-
-		ring->next_to_clean++;
 	}
 }
 
@@ -2077,10 +2071,14 @@ static uint16_t eth_ena_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		while (segments < ena_rx_ctx.descs) {
 			req_id = ena_rx_ctx.ena_bufs[segments].req_id;
 			rc = validate_rx_req_id(rx_ring, req_id);
-			if (unlikely(rc))
+			if (unlikely(rc)) {
+				if (segments != 0)
+					rte_mbuf_raw_free(mbuf_head);
 				break;
+			}
 
 			mbuf = rx_buff_info[req_id];
+			rx_buff_info[req_id] = NULL;
 			mbuf->data_len = ena_rx_ctx.ena_bufs[segments].len;
 			mbuf->data_off = RTE_PKTMBUF_HEADROOM;
 			mbuf->refcnt = 1;
Signature · 1 line
2.14.1
#23 lore raw
In reply to Michal Krawczyk
Quoted 54 lines · Michal Krawczyk

Hi,

we are proud to announce ENAv2 driver for the DPDK.
It is already available for the Linux, and now also ENAv2 can be used with DPDK on the appropriate AWS instances.

To summarize, this release contains:

**New major features**
* LLQv2 which is Low Latency Queue v2. This feature reduces the latency of the packets by pushing the header directly through the PCI to the device, before the DMA is even triggered. This allows the NIC to asynchronously prepare for the next incoming packet, when the DMA will be finished.
* Independent configuration of HW Tx and Rx ring depths. Also, on some instances it is possible to create 8k Rx descriptors per ring.
* Additional doorbell check on Tx, to handle Tx more efficiently for big bursts of packets
* Per queue statistics
* Extended statistics using xstats DPDK API

**New major bug fixes**
* The reset routine was aligned with the DPDK API, so now it can be handled as in other PMDs
* Fixes for OOO completion
* Fixes for memory leaks due to port stops and starts in the middle of traffic

There are also minor bug fixes and features in addition to the ones mentioned above.

Michal Krawczyk (4):
net/ena: add LLQv2 support
net/ena: add per-queue software counters stats
docs: update ENA PMD documentation and features
net/ena: release of the ENAv2 driver (v2.0.0)

Rafal Kozik (15):
net/ena: update ena_com for the ENAv2
net/ena: pass number of CPUs to the host info structure net/ena: add reset reason in rx error
net/ena: add hw queues depth setup
net/ena: skip packet with wrong req_id net/ena: increase maximum Rx ring size net/ena: call additional doorbells if needed net/ena: destroy queues if start failed net/ena: reset should not reconfigure queues net/ena: adjust new line in log messages net/ena: add supported RSS offloads types net/ena: fix invalid reference to variable in union net/ena: fix cleanup for out of order packets net/ena: new way of getting rx drops
net/ena: update completion queue after cleanup

Quoted 2 lines

Solganik Alexander (1):
net/ena: expose ENA-specific statistics in extended stats

Series applied to dpdk-next-net/master, thanks.

(v3 of 14/20 used, for rest it is v1)