From d5fc5012bbae5e51a9be9f63372a1ef6fef10371 Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Wed, 18 Nov 2020 14:30:59 +0000 Subject: [PATCH] ena-com: Fix ena-com to allocate cdesc aligned to 4k The latest generation hardware requires IO CQ (completion queue) descriptors memory to be aligned to a 4K. It needs that feature for the best performance. Allocating unaligned descriptors will have a big performance impact as the packet processing in a HW won't be optimized properly. It's a critical fix, especially for the arm64 EC2 instances. --- ena_com.c | 26 ++++++++++++++------------ ena_com.h | 2 ++ ena_plat.h | 22 +++++++++++++++++----- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/ena_com.c b/ena_com.c index dde0c3357f63..266e39859102 100644 --- a/ena_com.c +++ b/ena_com.c @@ -449,19 +449,21 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev, 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, - io_cq->cdesc_addr.virt_addr, - io_cq->cdesc_addr.phys_addr, - io_cq->cdesc_addr.mem_handle, - ctx->numa_node, - prev_node); + ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(ena_dev->dmadev, + size, + io_cq->cdesc_addr.virt_addr, + io_cq->cdesc_addr.phys_addr, + io_cq->cdesc_addr.mem_handle, + ctx->numa_node, + prev_node, + ENA_CDESC_RING_SIZE_ALIGNMENT); if (!io_cq->cdesc_addr.virt_addr) { - ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, - size, - io_cq->cdesc_addr.virt_addr, - io_cq->cdesc_addr.phys_addr, - io_cq->cdesc_addr.mem_handle); + ENA_MEM_ALLOC_COHERENT_ALIGNED(ena_dev->dmadev, + size, + io_cq->cdesc_addr.virt_addr, + io_cq->cdesc_addr.phys_addr, + io_cq->cdesc_addr.mem_handle, + ENA_CDESC_RING_SIZE_ALIGNMENT); } if (!io_cq->cdesc_addr.virt_addr) { diff --git a/ena_com.h b/ena_com.h index c1b9540edd0b..b94728310fc9 100644 --- a/ena_com.h +++ b/ena_com.h @@ -51,6 +51,8 @@ #define ADMIN_CQ_SIZE(depth) ((depth) * sizeof(struct ena_admin_acq_entry)) #define ADMIN_AENQ_SIZE(depth) ((depth) * sizeof(struct ena_admin_aenq_entry)) +#define ENA_CDESC_RING_SIZE_ALIGNMENT (1 << 12) /* 4K */ + /*****************************************************************************/ /*****************************************************************************/ /* ENA adaptive interrupt moderation settings */ diff --git a/ena_plat.h b/ena_plat.h index e3536cdf3573..f096a5ff88d1 100644 --- a/ena_plat.h +++ b/ena_plat.h @@ -106,6 +106,8 @@ extern struct ena_bus_space ebs; #define ENA_ADMQ (1 << 8) /* Detailed info about admin queue. */ #define ENA_NETMAP (1 << 9) /* Detailed info about netmap. */ +#define DEFAULT_ALLOC_ALIGNMENT 8 + extern int ena_log_level; #define ena_trace_raw(level, fmt, args...) \ @@ -285,7 +287,7 @@ typedef uint64_t ena_time_t; void ena_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error); int ena_dma_alloc(device_t dmadev, bus_size_t size, ena_mem_handle_t *dma, - int mapflags); + int mapflags, bus_size_t alignment); static inline uint32_t ena_reg_read32(struct ena_bus *bus, bus_size_t offset) @@ -313,20 +315,30 @@ ena_reg_read32(struct ena_bus *bus, bus_size_t offset) (void)(size); \ free(ptr, M_DEVBUF); \ } while (0) -#define ENA_MEM_ALLOC_COHERENT_NODE(dmadev, size, virt, phys, handle, node, \ - dev_node) \ +#define ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(dmadev, size, virt, phys, \ + handle, node, dev_node, alignment) \ do { \ ((virt) = NULL); \ (void)(dev_node); \ } while (0) -#define ENA_MEM_ALLOC_COHERENT(dmadev, size, virt, phys, dma) \ +#define ENA_MEM_ALLOC_COHERENT_NODE(dmadev, size, virt, phys, handle, \ + node, dev_node) \ + ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(dmadev, size, virt, \ + phys, handle, node, dev_node, DEFAULT_ALLOC_ALIGNMENT) + +#define ENA_MEM_ALLOC_COHERENT_ALIGNED(dmadev, size, virt, phys, dma, \ + alignment) \ do { \ - ena_dma_alloc((dmadev), (size), &(dma), 0); \ + ena_dma_alloc((dmadev), (size), &(dma), 0, alignment); \ (virt) = (void *)(dma).vaddr; \ (phys) = (dma).paddr; \ } while (0) +#define ENA_MEM_ALLOC_COHERENT(dmadev, size, virt, phys, dma) \ + ENA_MEM_ALLOC_COHERENT_ALIGNED(dmadev, size, virt, \ + phys, dma, DEFAULT_ALLOC_ALIGNMENT) + #define ENA_MEM_FREE_COHERENT(dmadev, size, virt, phys, dma) \ do { \ (void)size; \