1702928afSMaciej Bielski /* SPDX-License-Identifier: BSD-3-Clause 2086c6b66SMichal Krawczyk * Copyright (c) 2015-2020 Amazon.com, Inc. or its affiliates. 399ecfbf8SJan Medala * All rights reserved. 499ecfbf8SJan Medala */ 599ecfbf8SJan Medala 699ecfbf8SJan Medala #include "ena_com.h" 799ecfbf8SJan Medala 899ecfbf8SJan Medala /*****************************************************************************/ 999ecfbf8SJan Medala /*****************************************************************************/ 1099ecfbf8SJan Medala 1199ecfbf8SJan Medala /* Timeout in micro-sec */ 123adcba9aSMichal Krawczyk #define ADMIN_CMD_TIMEOUT_US (3000000) 1399ecfbf8SJan Medala 143adcba9aSMichal Krawczyk #define ENA_ASYNC_QUEUE_DEPTH 16 1599ecfbf8SJan Medala #define ENA_ADMIN_QUEUE_DEPTH 32 1699ecfbf8SJan Medala 1799ecfbf8SJan Medala #define ENA_CTRL_MAJOR 0 1899ecfbf8SJan Medala #define ENA_CTRL_MINOR 0 1999ecfbf8SJan Medala #define ENA_CTRL_SUB_MINOR 1 2099ecfbf8SJan Medala 2199ecfbf8SJan Medala #define MIN_ENA_CTRL_VER \ 2299ecfbf8SJan Medala (((ENA_CTRL_MAJOR) << \ 2399ecfbf8SJan Medala (ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_SHIFT)) | \ 2499ecfbf8SJan Medala ((ENA_CTRL_MINOR) << \ 2599ecfbf8SJan Medala (ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_SHIFT)) | \ 2699ecfbf8SJan Medala (ENA_CTRL_SUB_MINOR)) 2799ecfbf8SJan Medala 2899ecfbf8SJan Medala #define ENA_DMA_ADDR_TO_UINT32_LOW(x) ((u32)((u64)(x))) 2999ecfbf8SJan Medala #define ENA_DMA_ADDR_TO_UINT32_HIGH(x) ((u32)(((u64)(x)) >> 32)) 3099ecfbf8SJan Medala 3199ecfbf8SJan Medala #define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF 3299ecfbf8SJan Medala 33b68309beSRafal Kozik #define ENA_COM_BOUNCE_BUFFER_CNTRL_CNT 4 34b68309beSRafal Kozik 353adcba9aSMichal Krawczyk #define ENA_REGS_ADMIN_INTR_MASK 1 363adcba9aSMichal Krawczyk 370c84e048SMichal Krawczyk #define ENA_MIN_ADMIN_POLL_US 100 380c84e048SMichal Krawczyk 390c84e048SMichal Krawczyk #define ENA_MAX_ADMIN_POLL_US 5000 4099ecfbf8SJan Medala 4199ecfbf8SJan Medala /*****************************************************************************/ 4299ecfbf8SJan Medala /*****************************************************************************/ 4399ecfbf8SJan Medala /*****************************************************************************/ 4499ecfbf8SJan Medala 4599ecfbf8SJan Medala enum ena_cmd_status { 4699ecfbf8SJan Medala ENA_CMD_SUBMITTED, 4799ecfbf8SJan Medala ENA_CMD_COMPLETED, 4899ecfbf8SJan Medala /* Abort - canceled by the driver */ 4999ecfbf8SJan Medala ENA_CMD_ABORTED, 5099ecfbf8SJan Medala }; 5199ecfbf8SJan Medala 5299ecfbf8SJan Medala struct ena_comp_ctx { 5399ecfbf8SJan Medala ena_wait_event_t wait_event; 5499ecfbf8SJan Medala struct ena_admin_acq_entry *user_cqe; 5599ecfbf8SJan Medala u32 comp_size; 5699ecfbf8SJan Medala enum ena_cmd_status status; 5799ecfbf8SJan Medala /* status from the device */ 5899ecfbf8SJan Medala u8 comp_status; 5999ecfbf8SJan Medala u8 cmd_opcode; 6099ecfbf8SJan Medala bool occupied; 6199ecfbf8SJan Medala }; 6299ecfbf8SJan Medala 633adcba9aSMichal Krawczyk struct ena_com_stats_ctx { 643adcba9aSMichal Krawczyk struct ena_admin_aq_get_stats_cmd get_cmd; 653adcba9aSMichal Krawczyk struct ena_admin_acq_get_stats_resp get_resp; 663adcba9aSMichal Krawczyk }; 673adcba9aSMichal Krawczyk 68b2b02edeSMichal Krawczyk static int ena_com_mem_addr_set(struct ena_com_dev *ena_dev, 6999ecfbf8SJan Medala struct ena_common_mem_addr *ena_addr, 7099ecfbf8SJan Medala dma_addr_t addr) 7199ecfbf8SJan Medala { 7299ecfbf8SJan Medala if ((addr & GENMASK_ULL(ena_dev->dma_addr_bits - 1, 0)) != addr) { 7399ecfbf8SJan Medala ena_trc_err("dma address has more bits that the device supports\n"); 7499ecfbf8SJan Medala return ENA_COM_INVAL; 7599ecfbf8SJan Medala } 7699ecfbf8SJan Medala 773adcba9aSMichal Krawczyk ena_addr->mem_addr_low = lower_32_bits(addr); 78a366fe41SMichal Krawczyk ena_addr->mem_addr_high = (u16)upper_32_bits(addr); 7999ecfbf8SJan Medala 8099ecfbf8SJan Medala return 0; 8199ecfbf8SJan Medala } 8299ecfbf8SJan Medala 8399ecfbf8SJan Medala static int ena_com_admin_init_sq(struct ena_com_admin_queue *queue) 8499ecfbf8SJan Medala { 853adcba9aSMichal Krawczyk struct ena_com_admin_sq *sq = &queue->sq; 863adcba9aSMichal Krawczyk u16 size = ADMIN_SQ_SIZE(queue->q_depth); 8799ecfbf8SJan Medala 883adcba9aSMichal Krawczyk ENA_MEM_ALLOC_COHERENT(queue->q_dmadev, size, sq->entries, sq->dma_addr, 893adcba9aSMichal Krawczyk sq->mem_handle); 903adcba9aSMichal Krawczyk 913adcba9aSMichal Krawczyk if (!sq->entries) { 92b2b02edeSMichal Krawczyk ena_trc_err("memory allocation failed\n"); 9399ecfbf8SJan Medala return ENA_COM_NO_MEM; 9499ecfbf8SJan Medala } 9599ecfbf8SJan Medala 963adcba9aSMichal Krawczyk sq->head = 0; 973adcba9aSMichal Krawczyk sq->tail = 0; 983adcba9aSMichal Krawczyk sq->phase = 1; 9999ecfbf8SJan Medala 1003adcba9aSMichal Krawczyk sq->db_addr = NULL; 10199ecfbf8SJan Medala 10299ecfbf8SJan Medala return 0; 10399ecfbf8SJan Medala } 10499ecfbf8SJan Medala 10599ecfbf8SJan Medala static int ena_com_admin_init_cq(struct ena_com_admin_queue *queue) 10699ecfbf8SJan Medala { 1073adcba9aSMichal Krawczyk struct ena_com_admin_cq *cq = &queue->cq; 1083adcba9aSMichal Krawczyk u16 size = ADMIN_CQ_SIZE(queue->q_depth); 10999ecfbf8SJan Medala 1103adcba9aSMichal Krawczyk ENA_MEM_ALLOC_COHERENT(queue->q_dmadev, size, cq->entries, cq->dma_addr, 1113adcba9aSMichal Krawczyk cq->mem_handle); 1123adcba9aSMichal Krawczyk 1133adcba9aSMichal Krawczyk if (!cq->entries) { 114b2b02edeSMichal Krawczyk ena_trc_err("memory allocation failed\n"); 11599ecfbf8SJan Medala return ENA_COM_NO_MEM; 11699ecfbf8SJan Medala } 11799ecfbf8SJan Medala 1183adcba9aSMichal Krawczyk cq->head = 0; 1193adcba9aSMichal Krawczyk cq->phase = 1; 12099ecfbf8SJan Medala 12199ecfbf8SJan Medala return 0; 12299ecfbf8SJan Medala } 12399ecfbf8SJan Medala 12499ecfbf8SJan Medala static int ena_com_admin_init_aenq(struct ena_com_dev *dev, 12599ecfbf8SJan Medala struct ena_aenq_handlers *aenq_handlers) 12699ecfbf8SJan Medala { 1273adcba9aSMichal Krawczyk struct ena_com_aenq *aenq = &dev->aenq; 12899ecfbf8SJan Medala u32 addr_low, addr_high, aenq_caps; 1293adcba9aSMichal Krawczyk u16 size; 13099ecfbf8SJan Medala 13199ecfbf8SJan Medala dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH; 1323adcba9aSMichal Krawczyk size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH); 1333adcba9aSMichal Krawczyk ENA_MEM_ALLOC_COHERENT(dev->dmadev, size, 1343adcba9aSMichal Krawczyk aenq->entries, 1353adcba9aSMichal Krawczyk aenq->dma_addr, 1363adcba9aSMichal Krawczyk aenq->mem_handle); 13799ecfbf8SJan Medala 1383adcba9aSMichal Krawczyk if (!aenq->entries) { 139b2b02edeSMichal Krawczyk ena_trc_err("memory allocation failed\n"); 14099ecfbf8SJan Medala return ENA_COM_NO_MEM; 14199ecfbf8SJan Medala } 14299ecfbf8SJan Medala 1433adcba9aSMichal Krawczyk aenq->head = aenq->q_depth; 1443adcba9aSMichal Krawczyk aenq->phase = 1; 14599ecfbf8SJan Medala 1463adcba9aSMichal Krawczyk addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(aenq->dma_addr); 1473adcba9aSMichal Krawczyk addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(aenq->dma_addr); 14899ecfbf8SJan Medala 1493adcba9aSMichal Krawczyk ENA_REG_WRITE32(dev->bus, addr_low, dev->reg_bar + ENA_REGS_AENQ_BASE_LO_OFF); 1503adcba9aSMichal Krawczyk ENA_REG_WRITE32(dev->bus, addr_high, dev->reg_bar + ENA_REGS_AENQ_BASE_HI_OFF); 15199ecfbf8SJan Medala 15299ecfbf8SJan Medala aenq_caps = 0; 15399ecfbf8SJan Medala aenq_caps |= dev->aenq.q_depth & ENA_REGS_AENQ_CAPS_AENQ_DEPTH_MASK; 15499ecfbf8SJan Medala aenq_caps |= (sizeof(struct ena_admin_aenq_entry) << 15599ecfbf8SJan Medala ENA_REGS_AENQ_CAPS_AENQ_ENTRY_SIZE_SHIFT) & 15699ecfbf8SJan Medala ENA_REGS_AENQ_CAPS_AENQ_ENTRY_SIZE_MASK; 1573adcba9aSMichal Krawczyk ENA_REG_WRITE32(dev->bus, aenq_caps, dev->reg_bar + ENA_REGS_AENQ_CAPS_OFF); 15899ecfbf8SJan Medala 1593adcba9aSMichal Krawczyk if (unlikely(!aenq_handlers)) { 16099ecfbf8SJan Medala ena_trc_err("aenq handlers pointer is NULL\n"); 1613adcba9aSMichal Krawczyk return ENA_COM_INVAL; 1623adcba9aSMichal Krawczyk } 16399ecfbf8SJan Medala 1643adcba9aSMichal Krawczyk aenq->aenq_handlers = aenq_handlers; 16599ecfbf8SJan Medala 16699ecfbf8SJan Medala return 0; 16799ecfbf8SJan Medala } 16899ecfbf8SJan Medala 169b2b02edeSMichal Krawczyk static void comp_ctxt_release(struct ena_com_admin_queue *queue, 17099ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx) 17199ecfbf8SJan Medala { 17299ecfbf8SJan Medala comp_ctx->occupied = false; 17399ecfbf8SJan Medala ATOMIC32_DEC(&queue->outstanding_cmds); 17499ecfbf8SJan Medala } 17599ecfbf8SJan Medala 17699ecfbf8SJan Medala static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *queue, 17799ecfbf8SJan Medala u16 command_id, bool capture) 17899ecfbf8SJan Medala { 1796dcee7cdSJan Medala if (unlikely(command_id >= queue->q_depth)) { 1806dcee7cdSJan Medala ena_trc_err("command id is larger than the queue size. cmd_id: %u queue size %d\n", 18199ecfbf8SJan Medala command_id, queue->q_depth); 1826dcee7cdSJan Medala return NULL; 1836dcee7cdSJan Medala } 18499ecfbf8SJan Medala 185b2b02edeSMichal Krawczyk if (unlikely(!queue->comp_ctx)) { 186b2b02edeSMichal Krawczyk ena_trc_err("Completion context is NULL\n"); 187b2b02edeSMichal Krawczyk return NULL; 188b2b02edeSMichal Krawczyk } 189b2b02edeSMichal Krawczyk 1906dcee7cdSJan Medala if (unlikely(queue->comp_ctx[command_id].occupied && capture)) { 1916dcee7cdSJan Medala ena_trc_err("Completion context is occupied\n"); 1926dcee7cdSJan Medala return NULL; 1936dcee7cdSJan Medala } 19499ecfbf8SJan Medala 19599ecfbf8SJan Medala if (capture) { 19699ecfbf8SJan Medala ATOMIC32_INC(&queue->outstanding_cmds); 19799ecfbf8SJan Medala queue->comp_ctx[command_id].occupied = true; 19899ecfbf8SJan Medala } 19999ecfbf8SJan Medala 20099ecfbf8SJan Medala return &queue->comp_ctx[command_id]; 20199ecfbf8SJan Medala } 20299ecfbf8SJan Medala 2033adcba9aSMichal Krawczyk static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queue *admin_queue, 20499ecfbf8SJan Medala struct ena_admin_aq_entry *cmd, 20599ecfbf8SJan Medala size_t cmd_size_in_bytes, 20699ecfbf8SJan Medala struct ena_admin_acq_entry *comp, 20799ecfbf8SJan Medala size_t comp_size_in_bytes) 20899ecfbf8SJan Medala { 20999ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 21099ecfbf8SJan Medala u16 tail_masked, cmd_id; 21199ecfbf8SJan Medala u16 queue_size_mask; 21299ecfbf8SJan Medala u16 cnt; 21399ecfbf8SJan Medala 21499ecfbf8SJan Medala queue_size_mask = admin_queue->q_depth - 1; 21599ecfbf8SJan Medala 21699ecfbf8SJan Medala tail_masked = admin_queue->sq.tail & queue_size_mask; 21799ecfbf8SJan Medala 21899ecfbf8SJan Medala /* In case of queue FULL */ 219b68309beSRafal Kozik cnt = (u16)ATOMIC32_READ(&admin_queue->outstanding_cmds); 22099ecfbf8SJan Medala if (cnt >= admin_queue->q_depth) { 2213adcba9aSMichal Krawczyk ena_trc_dbg("admin queue is full.\n"); 22299ecfbf8SJan Medala admin_queue->stats.out_of_space++; 22399ecfbf8SJan Medala return ERR_PTR(ENA_COM_NO_SPACE); 22499ecfbf8SJan Medala } 22599ecfbf8SJan Medala 22699ecfbf8SJan Medala cmd_id = admin_queue->curr_cmd_id; 22799ecfbf8SJan Medala 22899ecfbf8SJan Medala cmd->aq_common_descriptor.flags |= admin_queue->sq.phase & 22999ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_PHASE_MASK; 23099ecfbf8SJan Medala 23199ecfbf8SJan Medala cmd->aq_common_descriptor.command_id |= cmd_id & 23299ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_COMMAND_ID_MASK; 23399ecfbf8SJan Medala 23499ecfbf8SJan Medala comp_ctx = get_comp_ctxt(admin_queue, cmd_id, true); 2353adcba9aSMichal Krawczyk if (unlikely(!comp_ctx)) 2363adcba9aSMichal Krawczyk return ERR_PTR(ENA_COM_INVAL); 23799ecfbf8SJan Medala 23899ecfbf8SJan Medala comp_ctx->status = ENA_CMD_SUBMITTED; 23999ecfbf8SJan Medala comp_ctx->comp_size = (u32)comp_size_in_bytes; 24099ecfbf8SJan Medala comp_ctx->user_cqe = comp; 24199ecfbf8SJan Medala comp_ctx->cmd_opcode = cmd->aq_common_descriptor.opcode; 24299ecfbf8SJan Medala 24399ecfbf8SJan Medala ENA_WAIT_EVENT_CLEAR(comp_ctx->wait_event); 24499ecfbf8SJan Medala 24599ecfbf8SJan Medala memcpy(&admin_queue->sq.entries[tail_masked], cmd, cmd_size_in_bytes); 24699ecfbf8SJan Medala 24799ecfbf8SJan Medala admin_queue->curr_cmd_id = (admin_queue->curr_cmd_id + 1) & 24899ecfbf8SJan Medala queue_size_mask; 24999ecfbf8SJan Medala 25099ecfbf8SJan Medala admin_queue->sq.tail++; 25199ecfbf8SJan Medala admin_queue->stats.submitted_cmd++; 25299ecfbf8SJan Medala 25399ecfbf8SJan Medala if (unlikely((admin_queue->sq.tail & queue_size_mask) == 0)) 25499ecfbf8SJan Medala admin_queue->sq.phase = !admin_queue->sq.phase; 25599ecfbf8SJan Medala 256b68309beSRafal Kozik ENA_DB_SYNC(&admin_queue->sq.mem_handle); 2573adcba9aSMichal Krawczyk ENA_REG_WRITE32(admin_queue->bus, admin_queue->sq.tail, 2583adcba9aSMichal Krawczyk admin_queue->sq.db_addr); 25999ecfbf8SJan Medala 26099ecfbf8SJan Medala return comp_ctx; 26199ecfbf8SJan Medala } 26299ecfbf8SJan Medala 263b2b02edeSMichal Krawczyk static int ena_com_init_comp_ctxt(struct ena_com_admin_queue *queue) 26499ecfbf8SJan Medala { 26599ecfbf8SJan Medala size_t size = queue->q_depth * sizeof(struct ena_comp_ctx); 26699ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 26799ecfbf8SJan Medala u16 i; 26899ecfbf8SJan Medala 26999ecfbf8SJan Medala queue->comp_ctx = ENA_MEM_ALLOC(queue->q_dmadev, size); 27099ecfbf8SJan Medala if (unlikely(!queue->comp_ctx)) { 271b2b02edeSMichal Krawczyk ena_trc_err("memory allocation failed\n"); 27299ecfbf8SJan Medala return ENA_COM_NO_MEM; 27399ecfbf8SJan Medala } 27499ecfbf8SJan Medala 27599ecfbf8SJan Medala for (i = 0; i < queue->q_depth; i++) { 27699ecfbf8SJan Medala comp_ctx = get_comp_ctxt(queue, i, false); 2776dcee7cdSJan Medala if (comp_ctx) 27899ecfbf8SJan Medala ENA_WAIT_EVENT_INIT(comp_ctx->wait_event); 27999ecfbf8SJan Medala } 28099ecfbf8SJan Medala 28199ecfbf8SJan Medala return 0; 28299ecfbf8SJan Medala } 28399ecfbf8SJan Medala 2843adcba9aSMichal Krawczyk static struct ena_comp_ctx *ena_com_submit_admin_cmd(struct ena_com_admin_queue *admin_queue, 28599ecfbf8SJan Medala struct ena_admin_aq_entry *cmd, 28699ecfbf8SJan Medala size_t cmd_size_in_bytes, 28799ecfbf8SJan Medala struct ena_admin_acq_entry *comp, 28899ecfbf8SJan Medala size_t comp_size_in_bytes) 28999ecfbf8SJan Medala { 29023a70746SDaniel Mrzyglod unsigned long flags = 0; 29199ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 29299ecfbf8SJan Medala 29399ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 29499ecfbf8SJan Medala if (unlikely(!admin_queue->running_state)) { 29599ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 29699ecfbf8SJan Medala return ERR_PTR(ENA_COM_NO_DEVICE); 29799ecfbf8SJan Medala } 29899ecfbf8SJan Medala comp_ctx = __ena_com_submit_admin_cmd(admin_queue, cmd, 29999ecfbf8SJan Medala cmd_size_in_bytes, 30099ecfbf8SJan Medala comp, 30199ecfbf8SJan Medala comp_size_in_bytes); 3023adcba9aSMichal Krawczyk if (IS_ERR(comp_ctx)) 3036dcee7cdSJan Medala admin_queue->running_state = false; 30499ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 30599ecfbf8SJan Medala 30699ecfbf8SJan Medala return comp_ctx; 30799ecfbf8SJan Medala } 30899ecfbf8SJan Medala 30999ecfbf8SJan Medala static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, 3106dcee7cdSJan Medala struct ena_com_create_io_ctx *ctx, 31199ecfbf8SJan Medala struct ena_com_io_sq *io_sq) 31299ecfbf8SJan Medala { 31399ecfbf8SJan Medala size_t size; 31462e82667SFerruh Yigit int dev_node = 0; 31599ecfbf8SJan Medala 3163adcba9aSMichal Krawczyk memset(&io_sq->desc_addr, 0x0, sizeof(io_sq->desc_addr)); 31799ecfbf8SJan Medala 318b68309beSRafal Kozik io_sq->dma_addr_bits = (u8)ena_dev->dma_addr_bits; 31999ecfbf8SJan Medala io_sq->desc_entry_size = 32099ecfbf8SJan Medala (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ? 32199ecfbf8SJan Medala sizeof(struct ena_eth_io_tx_desc) : 32299ecfbf8SJan Medala sizeof(struct ena_eth_io_rx_desc); 32399ecfbf8SJan Medala 32499ecfbf8SJan Medala size = io_sq->desc_entry_size * io_sq->q_depth; 325b68309beSRafal Kozik io_sq->bus = ena_dev->bus; 32699ecfbf8SJan Medala 3273d3edc26SJan Medala if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) { 3283d3edc26SJan Medala ENA_MEM_ALLOC_COHERENT_NODE(ena_dev->dmadev, 3293d3edc26SJan Medala size, 3303d3edc26SJan Medala io_sq->desc_addr.virt_addr, 3313d3edc26SJan Medala io_sq->desc_addr.phys_addr, 3323adcba9aSMichal Krawczyk io_sq->desc_addr.mem_handle, 3333d3edc26SJan Medala ctx->numa_node, 3343d3edc26SJan Medala dev_node); 3353adcba9aSMichal Krawczyk if (!io_sq->desc_addr.virt_addr) { 33699ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 33799ecfbf8SJan Medala size, 33899ecfbf8SJan Medala io_sq->desc_addr.virt_addr, 33999ecfbf8SJan Medala io_sq->desc_addr.phys_addr, 34099ecfbf8SJan Medala io_sq->desc_addr.mem_handle); 3413adcba9aSMichal Krawczyk } 34299ecfbf8SJan Medala 34399ecfbf8SJan Medala if (!io_sq->desc_addr.virt_addr) { 344b2b02edeSMichal Krawczyk ena_trc_err("memory allocation failed\n"); 34599ecfbf8SJan Medala return ENA_COM_NO_MEM; 34699ecfbf8SJan Medala } 347b68309beSRafal Kozik } 348b68309beSRafal Kozik 349b68309beSRafal Kozik if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 350b68309beSRafal Kozik /* Allocate bounce buffers */ 351b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.buffer_size = 352b2b02edeSMichal Krawczyk ena_dev->llq_info.desc_list_entry_size; 353b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.buffers_num = 354b2b02edeSMichal Krawczyk ENA_COM_BOUNCE_BUFFER_CNTRL_CNT; 355b68309beSRafal Kozik io_sq->bounce_buf_ctrl.next_to_use = 0; 356b68309beSRafal Kozik 357b2b02edeSMichal Krawczyk size = io_sq->bounce_buf_ctrl.buffer_size * 358b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.buffers_num; 359b68309beSRafal Kozik 360b68309beSRafal Kozik ENA_MEM_ALLOC_NODE(ena_dev->dmadev, 361b68309beSRafal Kozik size, 362b68309beSRafal Kozik io_sq->bounce_buf_ctrl.base_buffer, 363b68309beSRafal Kozik ctx->numa_node, 364b68309beSRafal Kozik dev_node); 365b68309beSRafal Kozik if (!io_sq->bounce_buf_ctrl.base_buffer) 366b68309beSRafal Kozik io_sq->bounce_buf_ctrl.base_buffer = ENA_MEM_ALLOC(ena_dev->dmadev, size); 367b68309beSRafal Kozik 368b68309beSRafal Kozik if (!io_sq->bounce_buf_ctrl.base_buffer) { 369b2b02edeSMichal Krawczyk ena_trc_err("bounce buffer memory allocation failed\n"); 370b68309beSRafal Kozik return ENA_COM_NO_MEM; 371b68309beSRafal Kozik } 372b68309beSRafal Kozik 373b2b02edeSMichal Krawczyk memcpy(&io_sq->llq_info, &ena_dev->llq_info, 374b2b02edeSMichal Krawczyk sizeof(io_sq->llq_info)); 375b68309beSRafal Kozik 376b68309beSRafal Kozik /* Initiate the first bounce buffer */ 377b68309beSRafal Kozik io_sq->llq_buf_ctrl.curr_bounce_buf = 378b68309beSRafal Kozik ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl); 379b68309beSRafal Kozik memset(io_sq->llq_buf_ctrl.curr_bounce_buf, 380b68309beSRafal Kozik 0x0, io_sq->llq_info.desc_list_entry_size); 381b68309beSRafal Kozik io_sq->llq_buf_ctrl.descs_left_in_line = 382b68309beSRafal Kozik io_sq->llq_info.descs_num_before_header; 383f1453604SMichal Krawczyk io_sq->disable_meta_caching = 384f1453604SMichal Krawczyk io_sq->llq_info.disable_meta_caching; 385b68309beSRafal Kozik 386b68309beSRafal Kozik if (io_sq->llq_info.max_entries_in_tx_burst > 0) 387b68309beSRafal Kozik io_sq->entries_in_tx_burst_left = 388b68309beSRafal Kozik io_sq->llq_info.max_entries_in_tx_burst; 389b68309beSRafal Kozik } 39099ecfbf8SJan Medala 39199ecfbf8SJan Medala io_sq->tail = 0; 39299ecfbf8SJan Medala io_sq->next_to_comp = 0; 39399ecfbf8SJan Medala io_sq->phase = 1; 39499ecfbf8SJan Medala 39599ecfbf8SJan Medala return 0; 39699ecfbf8SJan Medala } 39799ecfbf8SJan Medala 39899ecfbf8SJan Medala static int ena_com_init_io_cq(struct ena_com_dev *ena_dev, 3996dcee7cdSJan Medala struct ena_com_create_io_ctx *ctx, 40099ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 40199ecfbf8SJan Medala { 40299ecfbf8SJan Medala size_t size; 40362e82667SFerruh Yigit int prev_node = 0; 40499ecfbf8SJan Medala 4053adcba9aSMichal Krawczyk memset(&io_cq->cdesc_addr, 0x0, sizeof(io_cq->cdesc_addr)); 40699ecfbf8SJan Medala 40799ecfbf8SJan Medala /* Use the basic completion descriptor for Rx */ 40899ecfbf8SJan Medala io_cq->cdesc_entry_size_in_bytes = 40999ecfbf8SJan Medala (io_cq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ? 41099ecfbf8SJan Medala sizeof(struct ena_eth_io_tx_cdesc) : 41199ecfbf8SJan Medala sizeof(struct ena_eth_io_rx_cdesc_base); 41299ecfbf8SJan Medala 41399ecfbf8SJan Medala size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth; 414b68309beSRafal Kozik io_cq->bus = ena_dev->bus; 41599ecfbf8SJan Medala 416*4be6bc7fSMichal Krawczyk ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(ena_dev->dmadev, 4173d3edc26SJan Medala size, 4183d3edc26SJan Medala io_cq->cdesc_addr.virt_addr, 4193d3edc26SJan Medala io_cq->cdesc_addr.phys_addr, 4203adcba9aSMichal Krawczyk io_cq->cdesc_addr.mem_handle, 4213d3edc26SJan Medala ctx->numa_node, 422*4be6bc7fSMichal Krawczyk prev_node, 423*4be6bc7fSMichal Krawczyk ENA_CDESC_RING_SIZE_ALIGNMENT); 4243adcba9aSMichal Krawczyk if (!io_cq->cdesc_addr.virt_addr) { 425*4be6bc7fSMichal Krawczyk ENA_MEM_ALLOC_COHERENT_ALIGNED(ena_dev->dmadev, 42699ecfbf8SJan Medala size, 42799ecfbf8SJan Medala io_cq->cdesc_addr.virt_addr, 42899ecfbf8SJan Medala io_cq->cdesc_addr.phys_addr, 429*4be6bc7fSMichal Krawczyk io_cq->cdesc_addr.mem_handle, 430*4be6bc7fSMichal Krawczyk ENA_CDESC_RING_SIZE_ALIGNMENT); 4313adcba9aSMichal Krawczyk } 43299ecfbf8SJan Medala 43399ecfbf8SJan Medala if (!io_cq->cdesc_addr.virt_addr) { 434b2b02edeSMichal Krawczyk ena_trc_err("memory allocation failed\n"); 43599ecfbf8SJan Medala return ENA_COM_NO_MEM; 43699ecfbf8SJan Medala } 43799ecfbf8SJan Medala 43899ecfbf8SJan Medala io_cq->phase = 1; 43999ecfbf8SJan Medala io_cq->head = 0; 44099ecfbf8SJan Medala 44199ecfbf8SJan Medala return 0; 44299ecfbf8SJan Medala } 44399ecfbf8SJan Medala 4443adcba9aSMichal Krawczyk static void ena_com_handle_single_admin_completion(struct ena_com_admin_queue *admin_queue, 44599ecfbf8SJan Medala struct ena_admin_acq_entry *cqe) 44699ecfbf8SJan Medala { 44799ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 44899ecfbf8SJan Medala u16 cmd_id; 44999ecfbf8SJan Medala 45099ecfbf8SJan Medala cmd_id = cqe->acq_common_descriptor.command & 45199ecfbf8SJan Medala ENA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID_MASK; 45299ecfbf8SJan Medala 45399ecfbf8SJan Medala comp_ctx = get_comp_ctxt(admin_queue, cmd_id, false); 4546dcee7cdSJan Medala if (unlikely(!comp_ctx)) { 4556dcee7cdSJan Medala ena_trc_err("comp_ctx is NULL. Changing the admin queue running state\n"); 4566dcee7cdSJan Medala admin_queue->running_state = false; 4576dcee7cdSJan Medala return; 4586dcee7cdSJan Medala } 45999ecfbf8SJan Medala 46099ecfbf8SJan Medala comp_ctx->status = ENA_CMD_COMPLETED; 46199ecfbf8SJan Medala comp_ctx->comp_status = cqe->acq_common_descriptor.status; 46299ecfbf8SJan Medala 46399ecfbf8SJan Medala if (comp_ctx->user_cqe) 46499ecfbf8SJan Medala memcpy(comp_ctx->user_cqe, (void *)cqe, comp_ctx->comp_size); 46599ecfbf8SJan Medala 46699ecfbf8SJan Medala if (!admin_queue->polling) 46799ecfbf8SJan Medala ENA_WAIT_EVENT_SIGNAL(comp_ctx->wait_event); 46899ecfbf8SJan Medala } 46999ecfbf8SJan Medala 4703adcba9aSMichal Krawczyk static void ena_com_handle_admin_completion(struct ena_com_admin_queue *admin_queue) 47199ecfbf8SJan Medala { 47299ecfbf8SJan Medala struct ena_admin_acq_entry *cqe = NULL; 47399ecfbf8SJan Medala u16 comp_num = 0; 47499ecfbf8SJan Medala u16 head_masked; 47599ecfbf8SJan Medala u8 phase; 47699ecfbf8SJan Medala 47799ecfbf8SJan Medala head_masked = admin_queue->cq.head & (admin_queue->q_depth - 1); 47899ecfbf8SJan Medala phase = admin_queue->cq.phase; 47999ecfbf8SJan Medala 48099ecfbf8SJan Medala cqe = &admin_queue->cq.entries[head_masked]; 48199ecfbf8SJan Medala 48299ecfbf8SJan Medala /* Go over all the completions */ 483b68309beSRafal Kozik while ((READ_ONCE8(cqe->acq_common_descriptor.flags) & 48499ecfbf8SJan Medala ENA_ADMIN_ACQ_COMMON_DESC_PHASE_MASK) == phase) { 48599ecfbf8SJan Medala /* Do not read the rest of the completion entry before the 48699ecfbf8SJan Medala * phase bit was validated 48799ecfbf8SJan Medala */ 488b68309beSRafal Kozik dma_rmb(); 48999ecfbf8SJan Medala ena_com_handle_single_admin_completion(admin_queue, cqe); 49099ecfbf8SJan Medala 49199ecfbf8SJan Medala head_masked++; 49299ecfbf8SJan Medala comp_num++; 49399ecfbf8SJan Medala if (unlikely(head_masked == admin_queue->q_depth)) { 49499ecfbf8SJan Medala head_masked = 0; 49599ecfbf8SJan Medala phase = !phase; 49699ecfbf8SJan Medala } 49799ecfbf8SJan Medala 49899ecfbf8SJan Medala cqe = &admin_queue->cq.entries[head_masked]; 49999ecfbf8SJan Medala } 50099ecfbf8SJan Medala 50199ecfbf8SJan Medala admin_queue->cq.head += comp_num; 50299ecfbf8SJan Medala admin_queue->cq.phase = phase; 50399ecfbf8SJan Medala admin_queue->sq.head += comp_num; 50499ecfbf8SJan Medala admin_queue->stats.completed_cmd += comp_num; 50599ecfbf8SJan Medala } 50699ecfbf8SJan Medala 50799ecfbf8SJan Medala static int ena_com_comp_status_to_errno(u8 comp_status) 50899ecfbf8SJan Medala { 50999ecfbf8SJan Medala if (unlikely(comp_status != 0)) 51099ecfbf8SJan Medala ena_trc_err("admin command failed[%u]\n", comp_status); 51199ecfbf8SJan Medala 51299ecfbf8SJan Medala switch (comp_status) { 51399ecfbf8SJan Medala case ENA_ADMIN_SUCCESS: 514b2b02edeSMichal Krawczyk return ENA_COM_OK; 51599ecfbf8SJan Medala case ENA_ADMIN_RESOURCE_ALLOCATION_FAILURE: 51699ecfbf8SJan Medala return ENA_COM_NO_MEM; 51799ecfbf8SJan Medala case ENA_ADMIN_UNSUPPORTED_OPCODE: 5183adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 51999ecfbf8SJan Medala case ENA_ADMIN_BAD_OPCODE: 52099ecfbf8SJan Medala case ENA_ADMIN_MALFORMED_REQUEST: 52199ecfbf8SJan Medala case ENA_ADMIN_ILLEGAL_PARAMETER: 52299ecfbf8SJan Medala case ENA_ADMIN_UNKNOWN_ERROR: 52399ecfbf8SJan Medala return ENA_COM_INVAL; 5248eaf9fedSMichal Krawczyk case ENA_ADMIN_RESOURCE_BUSY: 5258eaf9fedSMichal Krawczyk return ENA_COM_TRY_AGAIN; 52699ecfbf8SJan Medala } 52799ecfbf8SJan Medala 528b2b02edeSMichal Krawczyk return ENA_COM_INVAL; 52999ecfbf8SJan Medala } 53099ecfbf8SJan Medala 5310c84e048SMichal Krawczyk static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us) 5320c84e048SMichal Krawczyk { 5330c84e048SMichal Krawczyk delay_us = ENA_MAX32(ENA_MIN_ADMIN_POLL_US, delay_us); 5340c84e048SMichal Krawczyk delay_us = ENA_MIN32(delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US); 5350c84e048SMichal Krawczyk ENA_USLEEP(delay_us); 5360c84e048SMichal Krawczyk } 5370c84e048SMichal Krawczyk 5383adcba9aSMichal Krawczyk static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx, 53999ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue) 54099ecfbf8SJan Medala { 5415fe8c8a2SFerruh Yigit unsigned long flags = 0; 542b2b02edeSMichal Krawczyk ena_time_t timeout; 54399ecfbf8SJan Medala int ret; 5440c84e048SMichal Krawczyk u32 exp = 0; 54599ecfbf8SJan Medala 5463adcba9aSMichal Krawczyk timeout = ENA_GET_SYSTEM_TIMEOUT(admin_queue->completion_timeout); 54799ecfbf8SJan Medala 5483adcba9aSMichal Krawczyk while (1) { 5493adcba9aSMichal Krawczyk ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 5503adcba9aSMichal Krawczyk ena_com_handle_admin_completion(admin_queue); 5513adcba9aSMichal Krawczyk ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 5523adcba9aSMichal Krawczyk 5533adcba9aSMichal Krawczyk if (comp_ctx->status != ENA_CMD_SUBMITTED) 5543adcba9aSMichal Krawczyk break; 5553adcba9aSMichal Krawczyk 5563adcba9aSMichal Krawczyk if (ENA_TIME_EXPIRE(timeout)) { 55799ecfbf8SJan Medala ena_trc_err("Wait for completion (polling) timeout\n"); 55899ecfbf8SJan Medala /* ENA didn't have any completion */ 55999ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 56099ecfbf8SJan Medala admin_queue->stats.no_completion++; 56199ecfbf8SJan Medala admin_queue->running_state = false; 56299ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 56399ecfbf8SJan Medala 56499ecfbf8SJan Medala ret = ENA_COM_TIMER_EXPIRED; 56599ecfbf8SJan Medala goto err; 56699ecfbf8SJan Medala } 56799ecfbf8SJan Medala 5680c84e048SMichal Krawczyk ena_delay_exponential_backoff_us(exp++, 5690c84e048SMichal Krawczyk admin_queue->ena_dev->ena_min_poll_delay_us); 57099ecfbf8SJan Medala } 57199ecfbf8SJan Medala 57299ecfbf8SJan Medala if (unlikely(comp_ctx->status == ENA_CMD_ABORTED)) { 57399ecfbf8SJan Medala ena_trc_err("Command was aborted\n"); 57499ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 57599ecfbf8SJan Medala admin_queue->stats.aborted_cmd++; 57699ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 57799ecfbf8SJan Medala ret = ENA_COM_NO_DEVICE; 57899ecfbf8SJan Medala goto err; 57999ecfbf8SJan Medala } 58099ecfbf8SJan Medala 5813adcba9aSMichal Krawczyk ENA_WARN(comp_ctx->status != ENA_CMD_COMPLETED, 58299ecfbf8SJan Medala "Invalid comp status %d\n", comp_ctx->status); 58399ecfbf8SJan Medala 58499ecfbf8SJan Medala ret = ena_com_comp_status_to_errno(comp_ctx->comp_status); 58599ecfbf8SJan Medala err: 58699ecfbf8SJan Medala comp_ctxt_release(admin_queue, comp_ctx); 58799ecfbf8SJan Medala return ret; 58899ecfbf8SJan Medala } 58999ecfbf8SJan Medala 590b68309beSRafal Kozik /** 591b68309beSRafal Kozik * Set the LLQ configurations of the firmware 592b68309beSRafal Kozik * 593b2b02edeSMichal Krawczyk * The driver provides only the enabled feature values to the device, 594b68309beSRafal Kozik * which in turn, checks if they are supported. 595b68309beSRafal Kozik */ 596b68309beSRafal Kozik static int ena_com_set_llq(struct ena_com_dev *ena_dev) 597b68309beSRafal Kozik { 598b68309beSRafal Kozik struct ena_com_admin_queue *admin_queue; 599b68309beSRafal Kozik struct ena_admin_set_feat_cmd cmd; 600b68309beSRafal Kozik struct ena_admin_set_feat_resp resp; 601b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &ena_dev->llq_info; 602b68309beSRafal Kozik int ret; 603b68309beSRafal Kozik 604b68309beSRafal Kozik memset(&cmd, 0x0, sizeof(cmd)); 605b68309beSRafal Kozik admin_queue = &ena_dev->admin_queue; 606b68309beSRafal Kozik 607b68309beSRafal Kozik cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 608b68309beSRafal Kozik cmd.feat_common.feature_id = ENA_ADMIN_LLQ; 609b68309beSRafal Kozik 610b68309beSRafal Kozik cmd.u.llq.header_location_ctrl_enabled = llq_info->header_location_ctrl; 611b68309beSRafal Kozik cmd.u.llq.entry_size_ctrl_enabled = llq_info->desc_list_entry_size_ctrl; 612b68309beSRafal Kozik cmd.u.llq.desc_num_before_header_enabled = llq_info->descs_num_before_header; 613b68309beSRafal Kozik cmd.u.llq.descriptors_stride_ctrl_enabled = llq_info->desc_stride_ctrl; 614b68309beSRafal Kozik 6157df844b7SMichal Krawczyk cmd.u.llq.accel_mode.u.set.enabled_flags = 6167df844b7SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING) | 617f1453604SMichal Krawczyk BIT(ENA_ADMIN_LIMIT_TX_BURST); 618f1453604SMichal Krawczyk 619b68309beSRafal Kozik ret = ena_com_execute_admin_command(admin_queue, 620b68309beSRafal Kozik (struct ena_admin_aq_entry *)&cmd, 621b68309beSRafal Kozik sizeof(cmd), 622b68309beSRafal Kozik (struct ena_admin_acq_entry *)&resp, 623b68309beSRafal Kozik sizeof(resp)); 624b68309beSRafal Kozik 625b68309beSRafal Kozik if (unlikely(ret)) 626b68309beSRafal Kozik ena_trc_err("Failed to set LLQ configurations: %d\n", ret); 627b68309beSRafal Kozik 628b68309beSRafal Kozik return ret; 629b68309beSRafal Kozik } 630b68309beSRafal Kozik 631b68309beSRafal Kozik static int ena_com_config_llq_info(struct ena_com_dev *ena_dev, 632b68309beSRafal Kozik struct ena_admin_feature_llq_desc *llq_features, 633b68309beSRafal Kozik struct ena_llq_configurations *llq_default_cfg) 634b68309beSRafal Kozik { 635b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &ena_dev->llq_info; 6367df844b7SMichal Krawczyk struct ena_admin_accel_mode_get llq_accel_mode_get; 637b68309beSRafal Kozik u16 supported_feat; 638b68309beSRafal Kozik int rc; 639b68309beSRafal Kozik 640b68309beSRafal Kozik memset(llq_info, 0, sizeof(*llq_info)); 641b68309beSRafal Kozik 642b68309beSRafal Kozik supported_feat = llq_features->header_location_ctrl_supported; 643b68309beSRafal Kozik 644b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_header_location)) { 645b2b02edeSMichal Krawczyk llq_info->header_location_ctrl = 646b2b02edeSMichal Krawczyk llq_default_cfg->llq_header_location; 647b68309beSRafal Kozik } else { 648b68309beSRafal Kozik ena_trc_err("Invalid header location control, supported: 0x%x\n", 649b68309beSRafal Kozik supported_feat); 650b68309beSRafal Kozik return -EINVAL; 651b68309beSRafal Kozik } 652b68309beSRafal Kozik 653b68309beSRafal Kozik if (likely(llq_info->header_location_ctrl == ENA_ADMIN_INLINE_HEADER)) { 654b68309beSRafal Kozik supported_feat = llq_features->descriptors_stride_ctrl_supported; 655b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_stride_ctrl)) { 656b68309beSRafal Kozik llq_info->desc_stride_ctrl = llq_default_cfg->llq_stride_ctrl; 657b68309beSRafal Kozik } else { 658b68309beSRafal Kozik if (supported_feat & ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY) { 659b68309beSRafal Kozik llq_info->desc_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY; 660b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_SINGLE_DESC_PER_ENTRY) { 661b68309beSRafal Kozik llq_info->desc_stride_ctrl = ENA_ADMIN_SINGLE_DESC_PER_ENTRY; 662b68309beSRafal Kozik } else { 663b68309beSRafal Kozik ena_trc_err("Invalid desc_stride_ctrl, supported: 0x%x\n", 664b68309beSRafal Kozik supported_feat); 665b68309beSRafal Kozik return -EINVAL; 666b68309beSRafal Kozik } 667b68309beSRafal Kozik 668b2b02edeSMichal Krawczyk ena_trc_err("Default llq stride ctrl is not supported, performing fallback, default: 0x%x, supported: 0x%x, used: 0x%x\n", 669b68309beSRafal Kozik llq_default_cfg->llq_stride_ctrl, 670b68309beSRafal Kozik supported_feat, 671b68309beSRafal Kozik llq_info->desc_stride_ctrl); 672b68309beSRafal Kozik } 673b68309beSRafal Kozik } else { 674b68309beSRafal Kozik llq_info->desc_stride_ctrl = 0; 675b68309beSRafal Kozik } 676b68309beSRafal Kozik 677b68309beSRafal Kozik supported_feat = llq_features->entry_size_ctrl_supported; 678b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_ring_entry_size)) { 679b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = llq_default_cfg->llq_ring_entry_size; 680b68309beSRafal Kozik llq_info->desc_list_entry_size = llq_default_cfg->llq_ring_entry_size_value; 681b68309beSRafal Kozik } else { 682b68309beSRafal Kozik if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_128B) { 683b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_128B; 684b68309beSRafal Kozik llq_info->desc_list_entry_size = 128; 685b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_192B) { 686b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_192B; 687b68309beSRafal Kozik llq_info->desc_list_entry_size = 192; 688b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_256B) { 689b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_256B; 690b68309beSRafal Kozik llq_info->desc_list_entry_size = 256; 691b68309beSRafal Kozik } else { 692b68309beSRafal Kozik ena_trc_err("Invalid entry_size_ctrl, supported: 0x%x\n", supported_feat); 693b68309beSRafal Kozik return -EINVAL; 694b68309beSRafal Kozik } 695b68309beSRafal Kozik 696b2b02edeSMichal Krawczyk ena_trc_err("Default llq ring entry size is not supported, performing fallback, default: 0x%x, supported: 0x%x, used: 0x%x\n", 697b68309beSRafal Kozik llq_default_cfg->llq_ring_entry_size, 698b68309beSRafal Kozik supported_feat, 699b68309beSRafal Kozik llq_info->desc_list_entry_size); 700b68309beSRafal Kozik } 701b68309beSRafal Kozik if (unlikely(llq_info->desc_list_entry_size & 0x7)) { 702b68309beSRafal Kozik /* The desc list entry size should be whole multiply of 8 703b68309beSRafal Kozik * This requirement comes from __iowrite64_copy() 704b68309beSRafal Kozik */ 705b68309beSRafal Kozik ena_trc_err("illegal entry size %d\n", 706b68309beSRafal Kozik llq_info->desc_list_entry_size); 707b68309beSRafal Kozik return -EINVAL; 708b68309beSRafal Kozik } 709b68309beSRafal Kozik 710b68309beSRafal Kozik if (llq_info->desc_stride_ctrl == ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY) 711b68309beSRafal Kozik llq_info->descs_per_entry = llq_info->desc_list_entry_size / 712b68309beSRafal Kozik sizeof(struct ena_eth_io_tx_desc); 713b68309beSRafal Kozik else 714b68309beSRafal Kozik llq_info->descs_per_entry = 1; 715b68309beSRafal Kozik 716b68309beSRafal Kozik supported_feat = llq_features->desc_num_before_header_supported; 717b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_num_decs_before_header)) { 718b68309beSRafal Kozik llq_info->descs_num_before_header = llq_default_cfg->llq_num_decs_before_header; 719b68309beSRafal Kozik } else { 720b68309beSRafal Kozik if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2) { 721b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2; 722b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_1) { 723b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_1; 724b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_4) { 725b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_4; 726b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_8) { 727b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_8; 728b68309beSRafal Kozik } else { 729b68309beSRafal Kozik ena_trc_err("Invalid descs_num_before_header, supported: 0x%x\n", 730b68309beSRafal Kozik supported_feat); 731b68309beSRafal Kozik return -EINVAL; 732b68309beSRafal Kozik } 733b68309beSRafal Kozik 734b2b02edeSMichal Krawczyk ena_trc_err("Default llq num descs before header is not supported, performing fallback, default: 0x%x, supported: 0x%x, used: 0x%x\n", 735b68309beSRafal Kozik llq_default_cfg->llq_num_decs_before_header, 736b68309beSRafal Kozik supported_feat, 737b68309beSRafal Kozik llq_info->descs_num_before_header); 738b68309beSRafal Kozik } 739f1453604SMichal Krawczyk /* Check for accelerated queue supported */ 7407df844b7SMichal Krawczyk llq_accel_mode_get = llq_features->accel_mode.u.get; 741b68309beSRafal Kozik 7427df844b7SMichal Krawczyk llq_info->disable_meta_caching = 7437df844b7SMichal Krawczyk !!(llq_accel_mode_get.supported_flags & 7447df844b7SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING)); 7457df844b7SMichal Krawczyk 7467df844b7SMichal Krawczyk if (llq_accel_mode_get.supported_flags & BIT(ENA_ADMIN_LIMIT_TX_BURST)) 747b68309beSRafal Kozik llq_info->max_entries_in_tx_burst = 7487df844b7SMichal Krawczyk llq_accel_mode_get.max_tx_burst_size / 749f1453604SMichal Krawczyk llq_default_cfg->llq_ring_entry_size_value; 750b68309beSRafal Kozik 751b68309beSRafal Kozik rc = ena_com_set_llq(ena_dev); 752b68309beSRafal Kozik if (rc) 753b68309beSRafal Kozik ena_trc_err("Cannot set LLQ configuration: %d\n", rc); 754b68309beSRafal Kozik 755b2b02edeSMichal Krawczyk return rc; 756b68309beSRafal Kozik } 757b68309beSRafal Kozik 7583adcba9aSMichal Krawczyk static int ena_com_wait_and_process_admin_cq_interrupts(struct ena_comp_ctx *comp_ctx, 75999ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue) 76099ecfbf8SJan Medala { 76123a70746SDaniel Mrzyglod unsigned long flags = 0; 7623adcba9aSMichal Krawczyk int ret; 76399ecfbf8SJan Medala 76499ecfbf8SJan Medala ENA_WAIT_EVENT_WAIT(comp_ctx->wait_event, 7653adcba9aSMichal Krawczyk admin_queue->completion_timeout); 76699ecfbf8SJan Medala 76799ecfbf8SJan Medala /* In case the command wasn't completed find out the root cause. 76899ecfbf8SJan Medala * There might be 2 kinds of errors 76999ecfbf8SJan Medala * 1) No completion (timeout reached) 77099ecfbf8SJan Medala * 2) There is completion but the device didn't get any msi-x interrupt. 77199ecfbf8SJan Medala */ 77299ecfbf8SJan Medala if (unlikely(comp_ctx->status == ENA_CMD_SUBMITTED)) { 77399ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 77499ecfbf8SJan Medala ena_com_handle_admin_completion(admin_queue); 77599ecfbf8SJan Medala admin_queue->stats.no_completion++; 77699ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 77799ecfbf8SJan Medala 778b2b02edeSMichal Krawczyk if (comp_ctx->status == ENA_CMD_COMPLETED) { 779b2b02edeSMichal Krawczyk ena_trc_err("The ena device sent a completion but the driver didn't receive a MSI-X interrupt (cmd %d), autopolling mode is %s\n", 780b2b02edeSMichal Krawczyk comp_ctx->cmd_opcode, admin_queue->auto_polling ? "ON" : "OFF"); 781b2b02edeSMichal Krawczyk /* Check if fallback to polling is enabled */ 782b2b02edeSMichal Krawczyk if (admin_queue->auto_polling) 783b2b02edeSMichal Krawczyk admin_queue->polling = true; 784b2b02edeSMichal Krawczyk } else { 785b2b02edeSMichal Krawczyk ena_trc_err("The ena device didn't send a completion for the admin cmd %d status %d\n", 78699ecfbf8SJan Medala comp_ctx->cmd_opcode, comp_ctx->status); 787b2b02edeSMichal Krawczyk } 788b2b02edeSMichal Krawczyk /* Check if shifted to polling mode. 789b2b02edeSMichal Krawczyk * This will happen if there is a completion without an interrupt 790b2b02edeSMichal Krawczyk * and autopolling mode is enabled. Continuing normal execution in such case 791b2b02edeSMichal Krawczyk */ 792b2b02edeSMichal Krawczyk if (!admin_queue->polling) { 79399ecfbf8SJan Medala admin_queue->running_state = false; 79499ecfbf8SJan Medala ret = ENA_COM_TIMER_EXPIRED; 79599ecfbf8SJan Medala goto err; 79699ecfbf8SJan Medala } 797b2b02edeSMichal Krawczyk } 79899ecfbf8SJan Medala 79999ecfbf8SJan Medala ret = ena_com_comp_status_to_errno(comp_ctx->comp_status); 80099ecfbf8SJan Medala err: 80199ecfbf8SJan Medala comp_ctxt_release(admin_queue, comp_ctx); 80299ecfbf8SJan Medala return ret; 80399ecfbf8SJan Medala } 80499ecfbf8SJan Medala 80599ecfbf8SJan Medala /* This method read the hardware device register through posting writes 80699ecfbf8SJan Medala * and waiting for response 80799ecfbf8SJan Medala * On timeout the function will return ENA_MMIO_READ_TIMEOUT 80899ecfbf8SJan Medala */ 80999ecfbf8SJan Medala static u32 ena_com_reg_bar_read32(struct ena_com_dev *ena_dev, u16 offset) 81099ecfbf8SJan Medala { 81199ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 81299ecfbf8SJan Medala volatile struct ena_admin_ena_mmio_req_read_less_resp *read_resp = 81399ecfbf8SJan Medala mmio_read->read_resp; 8143adcba9aSMichal Krawczyk u32 mmio_read_reg, ret, i; 81523a70746SDaniel Mrzyglod unsigned long flags = 0; 8163adcba9aSMichal Krawczyk u32 timeout = mmio_read->reg_read_to; 81799ecfbf8SJan Medala 81899ecfbf8SJan Medala ENA_MIGHT_SLEEP(); 81999ecfbf8SJan Medala 8203adcba9aSMichal Krawczyk if (timeout == 0) 8213adcba9aSMichal Krawczyk timeout = ENA_REG_READ_TIMEOUT; 8223adcba9aSMichal Krawczyk 82399ecfbf8SJan Medala /* If readless is disabled, perform regular read */ 82499ecfbf8SJan Medala if (!mmio_read->readless_supported) 8253adcba9aSMichal Krawczyk return ENA_REG_READ32(ena_dev->bus, ena_dev->reg_bar + offset); 82699ecfbf8SJan Medala 82799ecfbf8SJan Medala ENA_SPINLOCK_LOCK(mmio_read->lock, flags); 82899ecfbf8SJan Medala mmio_read->seq_num++; 82999ecfbf8SJan Medala 83099ecfbf8SJan Medala read_resp->req_id = mmio_read->seq_num + 0xDEAD; 83199ecfbf8SJan Medala mmio_read_reg = (offset << ENA_REGS_MMIO_REG_READ_REG_OFF_SHIFT) & 83299ecfbf8SJan Medala ENA_REGS_MMIO_REG_READ_REG_OFF_MASK; 83399ecfbf8SJan Medala mmio_read_reg |= mmio_read->seq_num & 83499ecfbf8SJan Medala ENA_REGS_MMIO_REG_READ_REQ_ID_MASK; 83599ecfbf8SJan Medala 836b68309beSRafal Kozik ENA_REG_WRITE32(ena_dev->bus, mmio_read_reg, 837b68309beSRafal Kozik ena_dev->reg_bar + ENA_REGS_MMIO_REG_READ_OFF); 83899ecfbf8SJan Medala 8393adcba9aSMichal Krawczyk for (i = 0; i < timeout; i++) { 840b68309beSRafal Kozik if (READ_ONCE16(read_resp->req_id) == mmio_read->seq_num) 84199ecfbf8SJan Medala break; 84299ecfbf8SJan Medala 84399ecfbf8SJan Medala ENA_UDELAY(1); 84499ecfbf8SJan Medala } 84599ecfbf8SJan Medala 8463adcba9aSMichal Krawczyk if (unlikely(i == timeout)) { 84799ecfbf8SJan Medala ena_trc_err("reading reg failed for timeout. expected: req id[%hu] offset[%hu] actual: req id[%hu] offset[%hu]\n", 84899ecfbf8SJan Medala mmio_read->seq_num, 84999ecfbf8SJan Medala offset, 85099ecfbf8SJan Medala read_resp->req_id, 85199ecfbf8SJan Medala read_resp->reg_off); 85299ecfbf8SJan Medala ret = ENA_MMIO_READ_TIMEOUT; 85399ecfbf8SJan Medala goto err; 85499ecfbf8SJan Medala } 85599ecfbf8SJan Medala 8566dcee7cdSJan Medala if (read_resp->reg_off != offset) { 857b2b02edeSMichal Krawczyk ena_trc_err("Read failure: wrong offset provided\n"); 8586dcee7cdSJan Medala ret = ENA_MMIO_READ_TIMEOUT; 8596dcee7cdSJan Medala } else { 86099ecfbf8SJan Medala ret = read_resp->reg_val; 8616dcee7cdSJan Medala } 86299ecfbf8SJan Medala err: 86399ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(mmio_read->lock, flags); 86499ecfbf8SJan Medala 86599ecfbf8SJan Medala return ret; 86699ecfbf8SJan Medala } 86799ecfbf8SJan Medala 86899ecfbf8SJan Medala /* There are two types to wait for completion. 86999ecfbf8SJan Medala * Polling mode - wait until the completion is available. 87099ecfbf8SJan Medala * Async mode - wait on wait queue until the completion is ready 87199ecfbf8SJan Medala * (or the timeout expired). 87299ecfbf8SJan Medala * It is expected that the IRQ called ena_com_handle_admin_completion 87399ecfbf8SJan Medala * to mark the completions. 87499ecfbf8SJan Medala */ 8753adcba9aSMichal Krawczyk static int ena_com_wait_and_process_admin_cq(struct ena_comp_ctx *comp_ctx, 87699ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue) 87799ecfbf8SJan Medala { 87899ecfbf8SJan Medala if (admin_queue->polling) 87999ecfbf8SJan Medala return ena_com_wait_and_process_admin_cq_polling(comp_ctx, 88099ecfbf8SJan Medala admin_queue); 88199ecfbf8SJan Medala 88299ecfbf8SJan Medala return ena_com_wait_and_process_admin_cq_interrupts(comp_ctx, 88399ecfbf8SJan Medala admin_queue); 88499ecfbf8SJan Medala } 88599ecfbf8SJan Medala 88699ecfbf8SJan Medala static int ena_com_destroy_io_sq(struct ena_com_dev *ena_dev, 88799ecfbf8SJan Medala struct ena_com_io_sq *io_sq) 88899ecfbf8SJan Medala { 88999ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 89099ecfbf8SJan Medala struct ena_admin_aq_destroy_sq_cmd destroy_cmd; 89199ecfbf8SJan Medala struct ena_admin_acq_destroy_sq_resp_desc destroy_resp; 89299ecfbf8SJan Medala u8 direction; 89399ecfbf8SJan Medala int ret; 89499ecfbf8SJan Medala 8953adcba9aSMichal Krawczyk memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); 89699ecfbf8SJan Medala 89799ecfbf8SJan Medala if (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) 89899ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_TX; 89999ecfbf8SJan Medala else 90099ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_RX; 90199ecfbf8SJan Medala 90299ecfbf8SJan Medala destroy_cmd.sq.sq_identity |= (direction << 90399ecfbf8SJan Medala ENA_ADMIN_SQ_SQ_DIRECTION_SHIFT) & 90499ecfbf8SJan Medala ENA_ADMIN_SQ_SQ_DIRECTION_MASK; 90599ecfbf8SJan Medala 90699ecfbf8SJan Medala destroy_cmd.sq.sq_idx = io_sq->idx; 90799ecfbf8SJan Medala destroy_cmd.aq_common_descriptor.opcode = ENA_ADMIN_DESTROY_SQ; 90899ecfbf8SJan Medala 9093adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 91099ecfbf8SJan Medala (struct ena_admin_aq_entry *)&destroy_cmd, 91199ecfbf8SJan Medala sizeof(destroy_cmd), 91299ecfbf8SJan Medala (struct ena_admin_acq_entry *)&destroy_resp, 91399ecfbf8SJan Medala sizeof(destroy_resp)); 91499ecfbf8SJan Medala 91599ecfbf8SJan Medala if (unlikely(ret && (ret != ENA_COM_NO_DEVICE))) 91699ecfbf8SJan Medala ena_trc_err("failed to destroy io sq error: %d\n", ret); 91799ecfbf8SJan Medala 91899ecfbf8SJan Medala return ret; 91999ecfbf8SJan Medala } 92099ecfbf8SJan Medala 92199ecfbf8SJan Medala static void ena_com_io_queue_free(struct ena_com_dev *ena_dev, 92299ecfbf8SJan Medala struct ena_com_io_sq *io_sq, 92399ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 92499ecfbf8SJan Medala { 92599ecfbf8SJan Medala size_t size; 92699ecfbf8SJan Medala 92799ecfbf8SJan Medala if (io_cq->cdesc_addr.virt_addr) { 92899ecfbf8SJan Medala size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth; 92999ecfbf8SJan Medala 93099ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 93199ecfbf8SJan Medala size, 93299ecfbf8SJan Medala io_cq->cdesc_addr.virt_addr, 93399ecfbf8SJan Medala io_cq->cdesc_addr.phys_addr, 93499ecfbf8SJan Medala io_cq->cdesc_addr.mem_handle); 93599ecfbf8SJan Medala 93699ecfbf8SJan Medala io_cq->cdesc_addr.virt_addr = NULL; 93799ecfbf8SJan Medala } 93899ecfbf8SJan Medala 93999ecfbf8SJan Medala if (io_sq->desc_addr.virt_addr) { 94099ecfbf8SJan Medala size = io_sq->desc_entry_size * io_sq->q_depth; 94199ecfbf8SJan Medala 94299ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 94399ecfbf8SJan Medala size, 94499ecfbf8SJan Medala io_sq->desc_addr.virt_addr, 94599ecfbf8SJan Medala io_sq->desc_addr.phys_addr, 94699ecfbf8SJan Medala io_sq->desc_addr.mem_handle); 94799ecfbf8SJan Medala 94899ecfbf8SJan Medala io_sq->desc_addr.virt_addr = NULL; 94999ecfbf8SJan Medala } 950b68309beSRafal Kozik 951b68309beSRafal Kozik if (io_sq->bounce_buf_ctrl.base_buffer) { 952b2b02edeSMichal Krawczyk ENA_MEM_FREE(ena_dev->dmadev, 953b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.base_buffer, 954b2b02edeSMichal Krawczyk (io_sq->llq_info.desc_list_entry_size * ENA_COM_BOUNCE_BUFFER_CNTRL_CNT)); 955b68309beSRafal Kozik io_sq->bounce_buf_ctrl.base_buffer = NULL; 956b68309beSRafal Kozik } 95799ecfbf8SJan Medala } 95899ecfbf8SJan Medala 9593adcba9aSMichal Krawczyk static int wait_for_reset_state(struct ena_com_dev *ena_dev, u32 timeout, 9603adcba9aSMichal Krawczyk u16 exp_state) 96199ecfbf8SJan Medala { 9620c84e048SMichal Krawczyk u32 val, exp = 0; 9630c84e048SMichal Krawczyk ena_time_t timeout_stamp; 96499ecfbf8SJan Medala 9650c84e048SMichal Krawczyk /* Convert timeout from resolution of 100ms to us resolution. */ 9660c84e048SMichal Krawczyk timeout_stamp = ENA_GET_SYSTEM_TIMEOUT(100 * 1000 * timeout); 9673adcba9aSMichal Krawczyk 9680c84e048SMichal Krawczyk while (1) { 96999ecfbf8SJan Medala val = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF); 97099ecfbf8SJan Medala 97199ecfbf8SJan Medala if (unlikely(val == ENA_MMIO_READ_TIMEOUT)) { 97299ecfbf8SJan Medala ena_trc_err("Reg read timeout occurred\n"); 97399ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 97499ecfbf8SJan Medala } 97599ecfbf8SJan Medala 97699ecfbf8SJan Medala if ((val & ENA_REGS_DEV_STS_RESET_IN_PROGRESS_MASK) == 97799ecfbf8SJan Medala exp_state) 97899ecfbf8SJan Medala return 0; 97999ecfbf8SJan Medala 9800c84e048SMichal Krawczyk if (ENA_TIME_EXPIRE(timeout_stamp)) 98199ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 9820c84e048SMichal Krawczyk 9830c84e048SMichal Krawczyk ena_delay_exponential_backoff_us(exp++, ena_dev->ena_min_poll_delay_us); 9840c84e048SMichal Krawczyk } 98599ecfbf8SJan Medala } 98699ecfbf8SJan Medala 9873adcba9aSMichal Krawczyk static bool ena_com_check_supported_feature_id(struct ena_com_dev *ena_dev, 98899ecfbf8SJan Medala enum ena_admin_aq_feature_id feature_id) 98999ecfbf8SJan Medala { 99099ecfbf8SJan Medala u32 feature_mask = 1 << feature_id; 99199ecfbf8SJan Medala 99299ecfbf8SJan Medala /* Device attributes is always supported */ 99399ecfbf8SJan Medala if ((feature_id != ENA_ADMIN_DEVICE_ATTRIBUTES) && 99499ecfbf8SJan Medala !(ena_dev->supported_features & feature_mask)) 99599ecfbf8SJan Medala return false; 99699ecfbf8SJan Medala 99799ecfbf8SJan Medala return true; 99899ecfbf8SJan Medala } 99999ecfbf8SJan Medala 100099ecfbf8SJan Medala static int ena_com_get_feature_ex(struct ena_com_dev *ena_dev, 100199ecfbf8SJan Medala struct ena_admin_get_feat_resp *get_resp, 100299ecfbf8SJan Medala enum ena_admin_aq_feature_id feature_id, 100399ecfbf8SJan Medala dma_addr_t control_buf_dma_addr, 1004b68309beSRafal Kozik u32 control_buff_size, 1005b68309beSRafal Kozik u8 feature_ver) 100699ecfbf8SJan Medala { 100799ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 100899ecfbf8SJan Medala struct ena_admin_get_feat_cmd get_cmd; 100999ecfbf8SJan Medala int ret; 101099ecfbf8SJan Medala 101199ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, feature_id)) { 10123adcba9aSMichal Krawczyk ena_trc_dbg("Feature %d isn't supported\n", feature_id); 10133adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 101499ecfbf8SJan Medala } 101599ecfbf8SJan Medala 101699ecfbf8SJan Medala memset(&get_cmd, 0x0, sizeof(get_cmd)); 101799ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 101899ecfbf8SJan Medala 101999ecfbf8SJan Medala get_cmd.aq_common_descriptor.opcode = ENA_ADMIN_GET_FEATURE; 102099ecfbf8SJan Medala 102199ecfbf8SJan Medala if (control_buff_size) 102299ecfbf8SJan Medala get_cmd.aq_common_descriptor.flags = 102399ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 102499ecfbf8SJan Medala else 102599ecfbf8SJan Medala get_cmd.aq_common_descriptor.flags = 0; 102699ecfbf8SJan Medala 102799ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 102899ecfbf8SJan Medala &get_cmd.control_buffer.address, 102999ecfbf8SJan Medala control_buf_dma_addr); 103099ecfbf8SJan Medala if (unlikely(ret)) { 103199ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 103299ecfbf8SJan Medala return ret; 103399ecfbf8SJan Medala } 103499ecfbf8SJan Medala 103599ecfbf8SJan Medala get_cmd.control_buffer.length = control_buff_size; 1036b68309beSRafal Kozik get_cmd.feat_common.feature_version = feature_ver; 103799ecfbf8SJan Medala get_cmd.feat_common.feature_id = feature_id; 103899ecfbf8SJan Medala 103999ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 104099ecfbf8SJan Medala (struct ena_admin_aq_entry *) 104199ecfbf8SJan Medala &get_cmd, 104299ecfbf8SJan Medala sizeof(get_cmd), 104399ecfbf8SJan Medala (struct ena_admin_acq_entry *) 104499ecfbf8SJan Medala get_resp, 104599ecfbf8SJan Medala sizeof(*get_resp)); 104699ecfbf8SJan Medala 104799ecfbf8SJan Medala if (unlikely(ret)) 104899ecfbf8SJan Medala ena_trc_err("Failed to submit get_feature command %d error: %d\n", 104999ecfbf8SJan Medala feature_id, ret); 105099ecfbf8SJan Medala 105199ecfbf8SJan Medala return ret; 105299ecfbf8SJan Medala } 105399ecfbf8SJan Medala 105499ecfbf8SJan Medala static int ena_com_get_feature(struct ena_com_dev *ena_dev, 105599ecfbf8SJan Medala struct ena_admin_get_feat_resp *get_resp, 1056b68309beSRafal Kozik enum ena_admin_aq_feature_id feature_id, 1057b68309beSRafal Kozik u8 feature_ver) 105899ecfbf8SJan Medala { 105999ecfbf8SJan Medala return ena_com_get_feature_ex(ena_dev, 106099ecfbf8SJan Medala get_resp, 106199ecfbf8SJan Medala feature_id, 106299ecfbf8SJan Medala 0, 1063b68309beSRafal Kozik 0, 1064b68309beSRafal Kozik feature_ver); 106599ecfbf8SJan Medala } 106699ecfbf8SJan Medala 10673e55684eSMichal Krawczyk int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev) 10683e55684eSMichal Krawczyk { 10693e55684eSMichal Krawczyk return ena_dev->rss.hash_func; 10703e55684eSMichal Krawczyk } 10713e55684eSMichal Krawczyk 1072086c6b66SMichal Krawczyk static void ena_com_hash_key_fill_default_key(struct ena_com_dev *ena_dev) 1073086c6b66SMichal Krawczyk { 1074086c6b66SMichal Krawczyk struct ena_admin_feature_rss_flow_hash_control *hash_key = 1075086c6b66SMichal Krawczyk (ena_dev->rss).hash_key; 1076086c6b66SMichal Krawczyk 1077086c6b66SMichal Krawczyk ENA_RSS_FILL_KEY(&hash_key->key, sizeof(hash_key->key)); 1078720854c9SMichal Krawczyk /* The key buffer is stored in the device in an array of 1079720854c9SMichal Krawczyk * uint32 elements. 1080086c6b66SMichal Krawczyk */ 1081720854c9SMichal Krawczyk hash_key->keys_num = ENA_ADMIN_RSS_KEY_PARTS; 1082086c6b66SMichal Krawczyk } 1083086c6b66SMichal Krawczyk 108499ecfbf8SJan Medala static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev) 108599ecfbf8SJan Medala { 108699ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 108799ecfbf8SJan Medala 1088ff40db8dSMichal Krawczyk if (!ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_RSS_HASH_FUNCTION)) 1089ff40db8dSMichal Krawczyk return ENA_COM_UNSUPPORTED; 1090ff40db8dSMichal Krawczyk 109199ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 109299ecfbf8SJan Medala sizeof(*rss->hash_key), 109399ecfbf8SJan Medala rss->hash_key, 109499ecfbf8SJan Medala rss->hash_key_dma_addr, 109599ecfbf8SJan Medala rss->hash_key_mem_handle); 109699ecfbf8SJan Medala 109799ecfbf8SJan Medala if (unlikely(!rss->hash_key)) 109899ecfbf8SJan Medala return ENA_COM_NO_MEM; 109999ecfbf8SJan Medala 110099ecfbf8SJan Medala return 0; 110199ecfbf8SJan Medala } 110299ecfbf8SJan Medala 11036dcee7cdSJan Medala static void ena_com_hash_key_destroy(struct ena_com_dev *ena_dev) 110499ecfbf8SJan Medala { 110599ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 110699ecfbf8SJan Medala 110799ecfbf8SJan Medala if (rss->hash_key) 110899ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 110999ecfbf8SJan Medala sizeof(*rss->hash_key), 111099ecfbf8SJan Medala rss->hash_key, 111199ecfbf8SJan Medala rss->hash_key_dma_addr, 111299ecfbf8SJan Medala rss->hash_key_mem_handle); 111399ecfbf8SJan Medala rss->hash_key = NULL; 111499ecfbf8SJan Medala } 111599ecfbf8SJan Medala 111699ecfbf8SJan Medala static int ena_com_hash_ctrl_init(struct ena_com_dev *ena_dev) 111799ecfbf8SJan Medala { 111899ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 111999ecfbf8SJan Medala 112099ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 112199ecfbf8SJan Medala sizeof(*rss->hash_ctrl), 112299ecfbf8SJan Medala rss->hash_ctrl, 112399ecfbf8SJan Medala rss->hash_ctrl_dma_addr, 112499ecfbf8SJan Medala rss->hash_ctrl_mem_handle); 112599ecfbf8SJan Medala 11266dcee7cdSJan Medala if (unlikely(!rss->hash_ctrl)) 11276dcee7cdSJan Medala return ENA_COM_NO_MEM; 11286dcee7cdSJan Medala 112999ecfbf8SJan Medala return 0; 113099ecfbf8SJan Medala } 113199ecfbf8SJan Medala 11326dcee7cdSJan Medala static void ena_com_hash_ctrl_destroy(struct ena_com_dev *ena_dev) 113399ecfbf8SJan Medala { 113499ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 113599ecfbf8SJan Medala 113699ecfbf8SJan Medala if (rss->hash_ctrl) 113799ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 113899ecfbf8SJan Medala sizeof(*rss->hash_ctrl), 113999ecfbf8SJan Medala rss->hash_ctrl, 114099ecfbf8SJan Medala rss->hash_ctrl_dma_addr, 114199ecfbf8SJan Medala rss->hash_ctrl_mem_handle); 114299ecfbf8SJan Medala rss->hash_ctrl = NULL; 114399ecfbf8SJan Medala } 114499ecfbf8SJan Medala 114599ecfbf8SJan Medala static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev, 114699ecfbf8SJan Medala u16 log_size) 114799ecfbf8SJan Medala { 114899ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 114999ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 115099ecfbf8SJan Medala size_t tbl_size; 115199ecfbf8SJan Medala int ret; 115299ecfbf8SJan Medala 115399ecfbf8SJan Medala ret = ena_com_get_feature(ena_dev, &get_resp, 1154b68309beSRafal Kozik ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG, 0); 115599ecfbf8SJan Medala if (unlikely(ret)) 115699ecfbf8SJan Medala return ret; 115799ecfbf8SJan Medala 115899ecfbf8SJan Medala if ((get_resp.u.ind_table.min_size > log_size) || 115999ecfbf8SJan Medala (get_resp.u.ind_table.max_size < log_size)) { 116099ecfbf8SJan Medala ena_trc_err("indirect table size doesn't fit. requested size: %d while min is:%d and max %d\n", 116199ecfbf8SJan Medala 1 << log_size, 116299ecfbf8SJan Medala 1 << get_resp.u.ind_table.min_size, 116399ecfbf8SJan Medala 1 << get_resp.u.ind_table.max_size); 116499ecfbf8SJan Medala return ENA_COM_INVAL; 116599ecfbf8SJan Medala } 116699ecfbf8SJan Medala 11676dcee7cdSJan Medala tbl_size = (1ULL << log_size) * 116899ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 116999ecfbf8SJan Medala 117099ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 117199ecfbf8SJan Medala tbl_size, 117299ecfbf8SJan Medala rss->rss_ind_tbl, 117399ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 117499ecfbf8SJan Medala rss->rss_ind_tbl_mem_handle); 117599ecfbf8SJan Medala if (unlikely(!rss->rss_ind_tbl)) 117699ecfbf8SJan Medala goto mem_err1; 117799ecfbf8SJan Medala 11786dcee7cdSJan Medala tbl_size = (1ULL << log_size) * sizeof(u16); 117999ecfbf8SJan Medala rss->host_rss_ind_tbl = 118099ecfbf8SJan Medala ENA_MEM_ALLOC(ena_dev->dmadev, tbl_size); 118199ecfbf8SJan Medala if (unlikely(!rss->host_rss_ind_tbl)) 118299ecfbf8SJan Medala goto mem_err2; 118399ecfbf8SJan Medala 118499ecfbf8SJan Medala rss->tbl_log_size = log_size; 118599ecfbf8SJan Medala 118699ecfbf8SJan Medala return 0; 118799ecfbf8SJan Medala 118899ecfbf8SJan Medala mem_err2: 11896dcee7cdSJan Medala tbl_size = (1ULL << log_size) * 119099ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 119199ecfbf8SJan Medala 119299ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 119399ecfbf8SJan Medala tbl_size, 119499ecfbf8SJan Medala rss->rss_ind_tbl, 119599ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 119699ecfbf8SJan Medala rss->rss_ind_tbl_mem_handle); 119799ecfbf8SJan Medala rss->rss_ind_tbl = NULL; 119899ecfbf8SJan Medala mem_err1: 119999ecfbf8SJan Medala rss->tbl_log_size = 0; 120099ecfbf8SJan Medala return ENA_COM_NO_MEM; 120199ecfbf8SJan Medala } 120299ecfbf8SJan Medala 12036dcee7cdSJan Medala static void ena_com_indirect_table_destroy(struct ena_com_dev *ena_dev) 120499ecfbf8SJan Medala { 120599ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 12066dcee7cdSJan Medala size_t tbl_size = (1ULL << rss->tbl_log_size) * 120799ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 120899ecfbf8SJan Medala 120999ecfbf8SJan Medala if (rss->rss_ind_tbl) 121099ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 121199ecfbf8SJan Medala tbl_size, 121299ecfbf8SJan Medala rss->rss_ind_tbl, 121399ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 121499ecfbf8SJan Medala rss->rss_ind_tbl_mem_handle); 121599ecfbf8SJan Medala rss->rss_ind_tbl = NULL; 121699ecfbf8SJan Medala 121799ecfbf8SJan Medala if (rss->host_rss_ind_tbl) 1218b2b02edeSMichal Krawczyk ENA_MEM_FREE(ena_dev->dmadev, 1219b2b02edeSMichal Krawczyk rss->host_rss_ind_tbl, 1220b2b02edeSMichal Krawczyk ((1ULL << rss->tbl_log_size) * sizeof(u16))); 122199ecfbf8SJan Medala rss->host_rss_ind_tbl = NULL; 122299ecfbf8SJan Medala } 122399ecfbf8SJan Medala 122499ecfbf8SJan Medala static int ena_com_create_io_sq(struct ena_com_dev *ena_dev, 122599ecfbf8SJan Medala struct ena_com_io_sq *io_sq, u16 cq_idx) 122699ecfbf8SJan Medala { 122799ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 122899ecfbf8SJan Medala struct ena_admin_aq_create_sq_cmd create_cmd; 122999ecfbf8SJan Medala struct ena_admin_acq_create_sq_resp_desc cmd_completion; 123099ecfbf8SJan Medala u8 direction; 123199ecfbf8SJan Medala int ret; 123299ecfbf8SJan Medala 12333adcba9aSMichal Krawczyk memset(&create_cmd, 0x0, sizeof(create_cmd)); 123499ecfbf8SJan Medala 123599ecfbf8SJan Medala create_cmd.aq_common_descriptor.opcode = ENA_ADMIN_CREATE_SQ; 123699ecfbf8SJan Medala 123799ecfbf8SJan Medala if (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) 123899ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_TX; 123999ecfbf8SJan Medala else 124099ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_RX; 124199ecfbf8SJan Medala 124299ecfbf8SJan Medala create_cmd.sq_identity |= (direction << 124399ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_SQ_DIRECTION_SHIFT) & 124499ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_SQ_DIRECTION_MASK; 124599ecfbf8SJan Medala 124699ecfbf8SJan Medala create_cmd.sq_caps_2 |= io_sq->mem_queue_type & 124799ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_PLACEMENT_POLICY_MASK; 124899ecfbf8SJan Medala 124999ecfbf8SJan Medala create_cmd.sq_caps_2 |= (ENA_ADMIN_COMPLETION_POLICY_DESC << 125099ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_COMPLETION_POLICY_SHIFT) & 125199ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_COMPLETION_POLICY_MASK; 125299ecfbf8SJan Medala 125399ecfbf8SJan Medala create_cmd.sq_caps_3 |= 125499ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_IS_PHYSICALLY_CONTIGUOUS_MASK; 125599ecfbf8SJan Medala 125699ecfbf8SJan Medala create_cmd.cq_idx = cq_idx; 125799ecfbf8SJan Medala create_cmd.sq_depth = io_sq->q_depth; 125899ecfbf8SJan Medala 125999ecfbf8SJan Medala if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) { 126099ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 126199ecfbf8SJan Medala &create_cmd.sq_ba, 126299ecfbf8SJan Medala io_sq->desc_addr.phys_addr); 126399ecfbf8SJan Medala if (unlikely(ret)) { 126499ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 126599ecfbf8SJan Medala return ret; 126699ecfbf8SJan Medala } 126799ecfbf8SJan Medala } 126899ecfbf8SJan Medala 12693adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 127099ecfbf8SJan Medala (struct ena_admin_aq_entry *)&create_cmd, 127199ecfbf8SJan Medala sizeof(create_cmd), 127299ecfbf8SJan Medala (struct ena_admin_acq_entry *)&cmd_completion, 127399ecfbf8SJan Medala sizeof(cmd_completion)); 127499ecfbf8SJan Medala if (unlikely(ret)) { 127599ecfbf8SJan Medala ena_trc_err("Failed to create IO SQ. error: %d\n", ret); 127699ecfbf8SJan Medala return ret; 127799ecfbf8SJan Medala } 127899ecfbf8SJan Medala 127999ecfbf8SJan Medala io_sq->idx = cmd_completion.sq_idx; 128099ecfbf8SJan Medala 128199ecfbf8SJan Medala io_sq->db_addr = (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 128299ecfbf8SJan Medala (uintptr_t)cmd_completion.sq_doorbell_offset); 128399ecfbf8SJan Medala 128499ecfbf8SJan Medala if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 128599ecfbf8SJan Medala io_sq->header_addr = (u8 __iomem *)((uintptr_t)ena_dev->mem_bar 128699ecfbf8SJan Medala + cmd_completion.llq_headers_offset); 128799ecfbf8SJan Medala 128899ecfbf8SJan Medala io_sq->desc_addr.pbuf_dev_addr = 128999ecfbf8SJan Medala (u8 __iomem *)((uintptr_t)ena_dev->mem_bar + 129099ecfbf8SJan Medala cmd_completion.llq_descriptors_offset); 129199ecfbf8SJan Medala } 129299ecfbf8SJan Medala 129399ecfbf8SJan Medala ena_trc_dbg("created sq[%u], depth[%u]\n", io_sq->idx, io_sq->q_depth); 129499ecfbf8SJan Medala 129599ecfbf8SJan Medala return ret; 129699ecfbf8SJan Medala } 129799ecfbf8SJan Medala 129899ecfbf8SJan Medala static int ena_com_ind_tbl_convert_to_device(struct ena_com_dev *ena_dev) 129999ecfbf8SJan Medala { 130099ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 130199ecfbf8SJan Medala struct ena_com_io_sq *io_sq; 130299ecfbf8SJan Medala u16 qid; 130399ecfbf8SJan Medala int i; 130499ecfbf8SJan Medala 130599ecfbf8SJan Medala for (i = 0; i < 1 << rss->tbl_log_size; i++) { 130699ecfbf8SJan Medala qid = rss->host_rss_ind_tbl[i]; 130799ecfbf8SJan Medala if (qid >= ENA_TOTAL_NUM_QUEUES) 130899ecfbf8SJan Medala return ENA_COM_INVAL; 130999ecfbf8SJan Medala 131099ecfbf8SJan Medala io_sq = &ena_dev->io_sq_queues[qid]; 131199ecfbf8SJan Medala 131299ecfbf8SJan Medala if (io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX) 131399ecfbf8SJan Medala return ENA_COM_INVAL; 131499ecfbf8SJan Medala 131599ecfbf8SJan Medala rss->rss_ind_tbl[i].cq_idx = io_sq->idx; 131699ecfbf8SJan Medala } 131799ecfbf8SJan Medala 131899ecfbf8SJan Medala return 0; 131999ecfbf8SJan Medala } 132099ecfbf8SJan Medala 13213adcba9aSMichal Krawczyk static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev, 13226dcee7cdSJan Medala u16 intr_delay_resolution) 132399ecfbf8SJan Medala { 1324d2138b23SMichal Krawczyk u16 prev_intr_delay_resolution = ena_dev->intr_delay_resolution; 132599ecfbf8SJan Medala 1326d2138b23SMichal Krawczyk if (unlikely(!intr_delay_resolution)) { 132799ecfbf8SJan Medala ena_trc_err("Illegal intr_delay_resolution provided. Going to use default 1 usec resolution\n"); 1328d2138b23SMichal Krawczyk intr_delay_resolution = ENA_DEFAULT_INTR_DELAY_RESOLUTION; 132999ecfbf8SJan Medala } 133099ecfbf8SJan Medala 133199ecfbf8SJan Medala /* update Rx */ 1332d2138b23SMichal Krawczyk ena_dev->intr_moder_rx_interval = 1333d2138b23SMichal Krawczyk ena_dev->intr_moder_rx_interval * 1334d2138b23SMichal Krawczyk prev_intr_delay_resolution / 1335d2138b23SMichal Krawczyk intr_delay_resolution; 133699ecfbf8SJan Medala 133799ecfbf8SJan Medala /* update Tx */ 1338d2138b23SMichal Krawczyk ena_dev->intr_moder_tx_interval = 1339d2138b23SMichal Krawczyk ena_dev->intr_moder_tx_interval * 1340d2138b23SMichal Krawczyk prev_intr_delay_resolution / 1341d2138b23SMichal Krawczyk intr_delay_resolution; 1342d2138b23SMichal Krawczyk 1343d2138b23SMichal Krawczyk ena_dev->intr_delay_resolution = intr_delay_resolution; 134499ecfbf8SJan Medala } 134599ecfbf8SJan Medala 134699ecfbf8SJan Medala /*****************************************************************************/ 134799ecfbf8SJan Medala /******************************* API ******************************/ 134899ecfbf8SJan Medala /*****************************************************************************/ 134999ecfbf8SJan Medala 135099ecfbf8SJan Medala int ena_com_execute_admin_command(struct ena_com_admin_queue *admin_queue, 135199ecfbf8SJan Medala struct ena_admin_aq_entry *cmd, 135299ecfbf8SJan Medala size_t cmd_size, 135399ecfbf8SJan Medala struct ena_admin_acq_entry *comp, 135499ecfbf8SJan Medala size_t comp_size) 135599ecfbf8SJan Medala { 135699ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 13573adcba9aSMichal Krawczyk int ret; 135899ecfbf8SJan Medala 135999ecfbf8SJan Medala comp_ctx = ena_com_submit_admin_cmd(admin_queue, cmd, cmd_size, 136099ecfbf8SJan Medala comp, comp_size); 13613adcba9aSMichal Krawczyk if (IS_ERR(comp_ctx)) { 13623adcba9aSMichal Krawczyk if (comp_ctx == ERR_PTR(ENA_COM_NO_DEVICE)) 13633adcba9aSMichal Krawczyk ena_trc_dbg("Failed to submit command [%ld]\n", 13643adcba9aSMichal Krawczyk PTR_ERR(comp_ctx)); 13653adcba9aSMichal Krawczyk else 136699ecfbf8SJan Medala ena_trc_err("Failed to submit command [%ld]\n", 136799ecfbf8SJan Medala PTR_ERR(comp_ctx)); 13683adcba9aSMichal Krawczyk 136999ecfbf8SJan Medala return PTR_ERR(comp_ctx); 137099ecfbf8SJan Medala } 137199ecfbf8SJan Medala 137299ecfbf8SJan Medala ret = ena_com_wait_and_process_admin_cq(comp_ctx, admin_queue); 137399ecfbf8SJan Medala if (unlikely(ret)) { 137499ecfbf8SJan Medala if (admin_queue->running_state) 137599ecfbf8SJan Medala ena_trc_err("Failed to process command. ret = %d\n", 137699ecfbf8SJan Medala ret); 137799ecfbf8SJan Medala else 137899ecfbf8SJan Medala ena_trc_dbg("Failed to process command. ret = %d\n", 137999ecfbf8SJan Medala ret); 138099ecfbf8SJan Medala } 138199ecfbf8SJan Medala return ret; 138299ecfbf8SJan Medala } 138399ecfbf8SJan Medala 138499ecfbf8SJan Medala int ena_com_create_io_cq(struct ena_com_dev *ena_dev, 138599ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 138699ecfbf8SJan Medala { 138799ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 138899ecfbf8SJan Medala struct ena_admin_aq_create_cq_cmd create_cmd; 138999ecfbf8SJan Medala struct ena_admin_acq_create_cq_resp_desc cmd_completion; 139099ecfbf8SJan Medala int ret; 139199ecfbf8SJan Medala 13923adcba9aSMichal Krawczyk memset(&create_cmd, 0x0, sizeof(create_cmd)); 139399ecfbf8SJan Medala 139499ecfbf8SJan Medala create_cmd.aq_common_descriptor.opcode = ENA_ADMIN_CREATE_CQ; 139599ecfbf8SJan Medala 139699ecfbf8SJan Medala create_cmd.cq_caps_2 |= (io_cq->cdesc_entry_size_in_bytes / 4) & 139799ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; 139899ecfbf8SJan Medala create_cmd.cq_caps_1 |= 139999ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_CQ_CMD_INTERRUPT_MODE_ENABLED_MASK; 140099ecfbf8SJan Medala 140199ecfbf8SJan Medala create_cmd.msix_vector = io_cq->msix_vector; 140299ecfbf8SJan Medala create_cmd.cq_depth = io_cq->q_depth; 140399ecfbf8SJan Medala 140499ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 140599ecfbf8SJan Medala &create_cmd.cq_ba, 140699ecfbf8SJan Medala io_cq->cdesc_addr.phys_addr); 140799ecfbf8SJan Medala if (unlikely(ret)) { 140899ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 140999ecfbf8SJan Medala return ret; 141099ecfbf8SJan Medala } 141199ecfbf8SJan Medala 14123adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 141399ecfbf8SJan Medala (struct ena_admin_aq_entry *)&create_cmd, 141499ecfbf8SJan Medala sizeof(create_cmd), 141599ecfbf8SJan Medala (struct ena_admin_acq_entry *)&cmd_completion, 141699ecfbf8SJan Medala sizeof(cmd_completion)); 141799ecfbf8SJan Medala if (unlikely(ret)) { 141899ecfbf8SJan Medala ena_trc_err("Failed to create IO CQ. error: %d\n", ret); 141999ecfbf8SJan Medala return ret; 142099ecfbf8SJan Medala } 142199ecfbf8SJan Medala 142299ecfbf8SJan Medala io_cq->idx = cmd_completion.cq_idx; 142399ecfbf8SJan Medala 142499ecfbf8SJan Medala io_cq->unmask_reg = (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 14256dcee7cdSJan Medala cmd_completion.cq_interrupt_unmask_register_offset); 142699ecfbf8SJan Medala 14276dcee7cdSJan Medala if (cmd_completion.cq_head_db_register_offset) 142899ecfbf8SJan Medala io_cq->cq_head_db_reg = 142999ecfbf8SJan Medala (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 14306dcee7cdSJan Medala cmd_completion.cq_head_db_register_offset); 14316dcee7cdSJan Medala 14326dcee7cdSJan Medala if (cmd_completion.numa_node_register_offset) 14336dcee7cdSJan Medala io_cq->numa_node_cfg_reg = 14346dcee7cdSJan Medala (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 14356dcee7cdSJan Medala cmd_completion.numa_node_register_offset); 143699ecfbf8SJan Medala 143799ecfbf8SJan Medala ena_trc_dbg("created cq[%u], depth[%u]\n", io_cq->idx, io_cq->q_depth); 143899ecfbf8SJan Medala 143999ecfbf8SJan Medala return ret; 144099ecfbf8SJan Medala } 144199ecfbf8SJan Medala 144299ecfbf8SJan Medala int ena_com_get_io_handlers(struct ena_com_dev *ena_dev, u16 qid, 144399ecfbf8SJan Medala struct ena_com_io_sq **io_sq, 144499ecfbf8SJan Medala struct ena_com_io_cq **io_cq) 144599ecfbf8SJan Medala { 144699ecfbf8SJan Medala if (qid >= ENA_TOTAL_NUM_QUEUES) { 144799ecfbf8SJan Medala ena_trc_err("Invalid queue number %d but the max is %d\n", 144899ecfbf8SJan Medala qid, ENA_TOTAL_NUM_QUEUES); 144999ecfbf8SJan Medala return ENA_COM_INVAL; 145099ecfbf8SJan Medala } 145199ecfbf8SJan Medala 145299ecfbf8SJan Medala *io_sq = &ena_dev->io_sq_queues[qid]; 145399ecfbf8SJan Medala *io_cq = &ena_dev->io_cq_queues[qid]; 145499ecfbf8SJan Medala 145599ecfbf8SJan Medala return 0; 145699ecfbf8SJan Medala } 145799ecfbf8SJan Medala 145899ecfbf8SJan Medala void ena_com_abort_admin_commands(struct ena_com_dev *ena_dev) 145999ecfbf8SJan Medala { 146099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 146199ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 146299ecfbf8SJan Medala u16 i; 146399ecfbf8SJan Medala 146499ecfbf8SJan Medala if (!admin_queue->comp_ctx) 146599ecfbf8SJan Medala return; 146699ecfbf8SJan Medala 146799ecfbf8SJan Medala for (i = 0; i < admin_queue->q_depth; i++) { 146899ecfbf8SJan Medala comp_ctx = get_comp_ctxt(admin_queue, i, false); 14696dcee7cdSJan Medala if (unlikely(!comp_ctx)) 14706dcee7cdSJan Medala break; 14716dcee7cdSJan Medala 147299ecfbf8SJan Medala comp_ctx->status = ENA_CMD_ABORTED; 147399ecfbf8SJan Medala 147499ecfbf8SJan Medala ENA_WAIT_EVENT_SIGNAL(comp_ctx->wait_event); 147599ecfbf8SJan Medala } 147699ecfbf8SJan Medala } 147799ecfbf8SJan Medala 147899ecfbf8SJan Medala void ena_com_wait_for_abort_completion(struct ena_com_dev *ena_dev) 147999ecfbf8SJan Medala { 148099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 148123a70746SDaniel Mrzyglod unsigned long flags = 0; 14820c84e048SMichal Krawczyk u32 exp = 0; 148399ecfbf8SJan Medala 148499ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 148599ecfbf8SJan Medala while (ATOMIC32_READ(&admin_queue->outstanding_cmds) != 0) { 148699ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 14870c84e048SMichal Krawczyk ena_delay_exponential_backoff_us(exp++, ena_dev->ena_min_poll_delay_us); 148899ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 148999ecfbf8SJan Medala } 149099ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 149199ecfbf8SJan Medala } 149299ecfbf8SJan Medala 149399ecfbf8SJan Medala int ena_com_destroy_io_cq(struct ena_com_dev *ena_dev, 149499ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 149599ecfbf8SJan Medala { 149699ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 149799ecfbf8SJan Medala struct ena_admin_aq_destroy_cq_cmd destroy_cmd; 149899ecfbf8SJan Medala struct ena_admin_acq_destroy_cq_resp_desc destroy_resp; 149999ecfbf8SJan Medala int ret; 150099ecfbf8SJan Medala 15013adcba9aSMichal Krawczyk memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); 150299ecfbf8SJan Medala 150399ecfbf8SJan Medala destroy_cmd.cq_idx = io_cq->idx; 150499ecfbf8SJan Medala destroy_cmd.aq_common_descriptor.opcode = ENA_ADMIN_DESTROY_CQ; 150599ecfbf8SJan Medala 15063adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 150799ecfbf8SJan Medala (struct ena_admin_aq_entry *)&destroy_cmd, 150899ecfbf8SJan Medala sizeof(destroy_cmd), 150999ecfbf8SJan Medala (struct ena_admin_acq_entry *)&destroy_resp, 151099ecfbf8SJan Medala sizeof(destroy_resp)); 151199ecfbf8SJan Medala 151299ecfbf8SJan Medala if (unlikely(ret && (ret != ENA_COM_NO_DEVICE))) 151399ecfbf8SJan Medala ena_trc_err("Failed to destroy IO CQ. error: %d\n", ret); 151499ecfbf8SJan Medala 151599ecfbf8SJan Medala return ret; 151699ecfbf8SJan Medala } 151799ecfbf8SJan Medala 151899ecfbf8SJan Medala bool ena_com_get_admin_running_state(struct ena_com_dev *ena_dev) 151999ecfbf8SJan Medala { 152099ecfbf8SJan Medala return ena_dev->admin_queue.running_state; 152199ecfbf8SJan Medala } 152299ecfbf8SJan Medala 152399ecfbf8SJan Medala void ena_com_set_admin_running_state(struct ena_com_dev *ena_dev, bool state) 152499ecfbf8SJan Medala { 152599ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 152623a70746SDaniel Mrzyglod unsigned long flags = 0; 152799ecfbf8SJan Medala 152899ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 152999ecfbf8SJan Medala ena_dev->admin_queue.running_state = state; 153099ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 153199ecfbf8SJan Medala } 153299ecfbf8SJan Medala 153399ecfbf8SJan Medala void ena_com_admin_aenq_enable(struct ena_com_dev *ena_dev) 153499ecfbf8SJan Medala { 153599ecfbf8SJan Medala u16 depth = ena_dev->aenq.q_depth; 153699ecfbf8SJan Medala 15373adcba9aSMichal Krawczyk ENA_WARN(ena_dev->aenq.head != depth, "Invalid AENQ state\n"); 153899ecfbf8SJan Medala 153999ecfbf8SJan Medala /* Init head_db to mark that all entries in the queue 154099ecfbf8SJan Medala * are initially available 154199ecfbf8SJan Medala */ 15423adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, depth, ena_dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF); 154399ecfbf8SJan Medala } 154499ecfbf8SJan Medala 154599ecfbf8SJan Medala int ena_com_set_aenq_config(struct ena_com_dev *ena_dev, u32 groups_flag) 154699ecfbf8SJan Medala { 154799ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 154899ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 154999ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 155099ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 15513adcba9aSMichal Krawczyk int ret; 155299ecfbf8SJan Medala 1553b68309beSRafal Kozik ret = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_AENQ_CONFIG, 0); 155499ecfbf8SJan Medala if (ret) { 155599ecfbf8SJan Medala ena_trc_info("Can't get aenq configuration\n"); 155699ecfbf8SJan Medala return ret; 155799ecfbf8SJan Medala } 155899ecfbf8SJan Medala 155999ecfbf8SJan Medala if ((get_resp.u.aenq.supported_groups & groups_flag) != groups_flag) { 1560b68309beSRafal Kozik ena_trc_warn("Trying to set unsupported aenq events. supported flag: 0x%x asked flag: 0x%x\n", 156199ecfbf8SJan Medala get_resp.u.aenq.supported_groups, 156299ecfbf8SJan Medala groups_flag); 15633adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 156499ecfbf8SJan Medala } 156599ecfbf8SJan Medala 156699ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 156799ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 156899ecfbf8SJan Medala 156999ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 157099ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 0; 157199ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_AENQ_CONFIG; 157299ecfbf8SJan Medala cmd.u.aenq.enabled_groups = groups_flag; 157399ecfbf8SJan Medala 157499ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 157599ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 157699ecfbf8SJan Medala sizeof(cmd), 157799ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 157899ecfbf8SJan Medala sizeof(resp)); 157999ecfbf8SJan Medala 158099ecfbf8SJan Medala if (unlikely(ret)) 158199ecfbf8SJan Medala ena_trc_err("Failed to config AENQ ret: %d\n", ret); 158299ecfbf8SJan Medala 158399ecfbf8SJan Medala return ret; 158499ecfbf8SJan Medala } 158599ecfbf8SJan Medala 158699ecfbf8SJan Medala int ena_com_get_dma_width(struct ena_com_dev *ena_dev) 158799ecfbf8SJan Medala { 158899ecfbf8SJan Medala u32 caps = ena_com_reg_bar_read32(ena_dev, ENA_REGS_CAPS_OFF); 158999ecfbf8SJan Medala int width; 159099ecfbf8SJan Medala 159199ecfbf8SJan Medala if (unlikely(caps == ENA_MMIO_READ_TIMEOUT)) { 159299ecfbf8SJan Medala ena_trc_err("Reg read timeout occurred\n"); 159399ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 159499ecfbf8SJan Medala } 159599ecfbf8SJan Medala 159699ecfbf8SJan Medala width = (caps & ENA_REGS_CAPS_DMA_ADDR_WIDTH_MASK) >> 159799ecfbf8SJan Medala ENA_REGS_CAPS_DMA_ADDR_WIDTH_SHIFT; 159899ecfbf8SJan Medala 159999ecfbf8SJan Medala ena_trc_dbg("ENA dma width: %d\n", width); 160099ecfbf8SJan Medala 160199ecfbf8SJan Medala if ((width < 32) || width > ENA_MAX_PHYS_ADDR_SIZE_BITS) { 160299ecfbf8SJan Medala ena_trc_err("DMA width illegal value: %d\n", width); 160399ecfbf8SJan Medala return ENA_COM_INVAL; 160499ecfbf8SJan Medala } 160599ecfbf8SJan Medala 160699ecfbf8SJan Medala ena_dev->dma_addr_bits = width; 160799ecfbf8SJan Medala 160899ecfbf8SJan Medala return width; 160999ecfbf8SJan Medala } 161099ecfbf8SJan Medala 161199ecfbf8SJan Medala int ena_com_validate_version(struct ena_com_dev *ena_dev) 161299ecfbf8SJan Medala { 161399ecfbf8SJan Medala u32 ver; 161499ecfbf8SJan Medala u32 ctrl_ver; 161599ecfbf8SJan Medala u32 ctrl_ver_masked; 161699ecfbf8SJan Medala 161799ecfbf8SJan Medala /* Make sure the ENA version and the controller version are at least 161899ecfbf8SJan Medala * as the driver expects 161999ecfbf8SJan Medala */ 162099ecfbf8SJan Medala ver = ena_com_reg_bar_read32(ena_dev, ENA_REGS_VERSION_OFF); 162199ecfbf8SJan Medala ctrl_ver = ena_com_reg_bar_read32(ena_dev, 162299ecfbf8SJan Medala ENA_REGS_CONTROLLER_VERSION_OFF); 162399ecfbf8SJan Medala 162499ecfbf8SJan Medala if (unlikely((ver == ENA_MMIO_READ_TIMEOUT) || 162599ecfbf8SJan Medala (ctrl_ver == ENA_MMIO_READ_TIMEOUT))) { 162699ecfbf8SJan Medala ena_trc_err("Reg read timeout occurred\n"); 162799ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 162899ecfbf8SJan Medala } 162999ecfbf8SJan Medala 163099ecfbf8SJan Medala ena_trc_info("ena device version: %d.%d\n", 163199ecfbf8SJan Medala (ver & ENA_REGS_VERSION_MAJOR_VERSION_MASK) >> 163299ecfbf8SJan Medala ENA_REGS_VERSION_MAJOR_VERSION_SHIFT, 163399ecfbf8SJan Medala ver & ENA_REGS_VERSION_MINOR_VERSION_MASK); 163499ecfbf8SJan Medala 163599ecfbf8SJan Medala ena_trc_info("ena controller version: %d.%d.%d implementation version %d\n", 163699ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_MASK) 163799ecfbf8SJan Medala >> ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_SHIFT, 163899ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_MASK) 163999ecfbf8SJan Medala >> ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_SHIFT, 164099ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_SUBMINOR_VERSION_MASK), 164199ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_IMPL_ID_MASK) >> 164299ecfbf8SJan Medala ENA_REGS_CONTROLLER_VERSION_IMPL_ID_SHIFT); 164399ecfbf8SJan Medala 164499ecfbf8SJan Medala ctrl_ver_masked = 164599ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_MASK) | 164699ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_MASK) | 164799ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_SUBMINOR_VERSION_MASK); 164899ecfbf8SJan Medala 164999ecfbf8SJan Medala /* Validate the ctrl version without the implementation ID */ 165099ecfbf8SJan Medala if (ctrl_ver_masked < MIN_ENA_CTRL_VER) { 165199ecfbf8SJan Medala ena_trc_err("ENA ctrl version is lower than the minimal ctrl version the driver supports\n"); 165299ecfbf8SJan Medala return -1; 165399ecfbf8SJan Medala } 165499ecfbf8SJan Medala 165599ecfbf8SJan Medala return 0; 165699ecfbf8SJan Medala } 165799ecfbf8SJan Medala 165899ecfbf8SJan Medala void ena_com_admin_destroy(struct ena_com_dev *ena_dev) 165999ecfbf8SJan Medala { 166099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 16613adcba9aSMichal Krawczyk struct ena_com_admin_cq *cq = &admin_queue->cq; 16623adcba9aSMichal Krawczyk struct ena_com_admin_sq *sq = &admin_queue->sq; 16633adcba9aSMichal Krawczyk struct ena_com_aenq *aenq = &ena_dev->aenq; 16643adcba9aSMichal Krawczyk u16 size; 166599ecfbf8SJan Medala 1666f034d4bbSMichal Krawczyk if (admin_queue->comp_ctx) { 16673adcba9aSMichal Krawczyk ENA_WAIT_EVENT_DESTROY(admin_queue->comp_ctx->wait_event); 1668b2b02edeSMichal Krawczyk ENA_MEM_FREE(ena_dev->dmadev, 1669b2b02edeSMichal Krawczyk admin_queue->comp_ctx, 1670b2b02edeSMichal Krawczyk (admin_queue->q_depth * sizeof(struct ena_comp_ctx))); 1671f034d4bbSMichal Krawczyk } 1672f034d4bbSMichal Krawczyk 167399ecfbf8SJan Medala admin_queue->comp_ctx = NULL; 16743adcba9aSMichal Krawczyk size = ADMIN_SQ_SIZE(admin_queue->q_depth); 16753adcba9aSMichal Krawczyk if (sq->entries) 16763adcba9aSMichal Krawczyk ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, sq->entries, 16773adcba9aSMichal Krawczyk sq->dma_addr, sq->mem_handle); 16783adcba9aSMichal Krawczyk sq->entries = NULL; 167999ecfbf8SJan Medala 16803adcba9aSMichal Krawczyk size = ADMIN_CQ_SIZE(admin_queue->q_depth); 16813adcba9aSMichal Krawczyk if (cq->entries) 16823adcba9aSMichal Krawczyk ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, cq->entries, 16833adcba9aSMichal Krawczyk cq->dma_addr, cq->mem_handle); 16843adcba9aSMichal Krawczyk cq->entries = NULL; 168599ecfbf8SJan Medala 16863adcba9aSMichal Krawczyk size = ADMIN_AENQ_SIZE(aenq->q_depth); 168799ecfbf8SJan Medala if (ena_dev->aenq.entries) 16883adcba9aSMichal Krawczyk ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, aenq->entries, 16893adcba9aSMichal Krawczyk aenq->dma_addr, aenq->mem_handle); 16903adcba9aSMichal Krawczyk aenq->entries = NULL; 1691b68309beSRafal Kozik ENA_SPINLOCK_DESTROY(admin_queue->q_lock); 169299ecfbf8SJan Medala } 169399ecfbf8SJan Medala 169499ecfbf8SJan Medala void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling) 169599ecfbf8SJan Medala { 16963adcba9aSMichal Krawczyk u32 mask_value = 0; 16973adcba9aSMichal Krawczyk 16983adcba9aSMichal Krawczyk if (polling) 16993adcba9aSMichal Krawczyk mask_value = ENA_REGS_ADMIN_INTR_MASK; 17003adcba9aSMichal Krawczyk 1701b68309beSRafal Kozik ENA_REG_WRITE32(ena_dev->bus, mask_value, 1702b68309beSRafal Kozik ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF); 170399ecfbf8SJan Medala ena_dev->admin_queue.polling = polling; 170499ecfbf8SJan Medala } 170599ecfbf8SJan Medala 1706b2b02edeSMichal Krawczyk bool ena_com_get_admin_polling_mode(struct ena_com_dev *ena_dev) 1707b2b02edeSMichal Krawczyk { 1708b2b02edeSMichal Krawczyk return ena_dev->admin_queue.polling; 1709b2b02edeSMichal Krawczyk } 1710b2b02edeSMichal Krawczyk 1711b2b02edeSMichal Krawczyk void ena_com_set_admin_auto_polling_mode(struct ena_com_dev *ena_dev, 1712b2b02edeSMichal Krawczyk bool polling) 1713b2b02edeSMichal Krawczyk { 1714b2b02edeSMichal Krawczyk ena_dev->admin_queue.auto_polling = polling; 1715b2b02edeSMichal Krawczyk } 1716b2b02edeSMichal Krawczyk 171799ecfbf8SJan Medala int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev) 171899ecfbf8SJan Medala { 171999ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 172099ecfbf8SJan Medala 172199ecfbf8SJan Medala ENA_SPINLOCK_INIT(mmio_read->lock); 172299ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 172399ecfbf8SJan Medala sizeof(*mmio_read->read_resp), 172499ecfbf8SJan Medala mmio_read->read_resp, 172599ecfbf8SJan Medala mmio_read->read_resp_dma_addr, 172699ecfbf8SJan Medala mmio_read->read_resp_mem_handle); 172799ecfbf8SJan Medala if (unlikely(!mmio_read->read_resp)) 1728b68309beSRafal Kozik goto err; 172999ecfbf8SJan Medala 173099ecfbf8SJan Medala ena_com_mmio_reg_read_request_write_dev_addr(ena_dev); 173199ecfbf8SJan Medala 173299ecfbf8SJan Medala mmio_read->read_resp->req_id = 0x0; 173399ecfbf8SJan Medala mmio_read->seq_num = 0x0; 173499ecfbf8SJan Medala mmio_read->readless_supported = true; 173599ecfbf8SJan Medala 173699ecfbf8SJan Medala return 0; 1737b68309beSRafal Kozik 1738b68309beSRafal Kozik err: 1739b68309beSRafal Kozik ENA_SPINLOCK_DESTROY(mmio_read->lock); 1740b68309beSRafal Kozik return ENA_COM_NO_MEM; 174199ecfbf8SJan Medala } 174299ecfbf8SJan Medala 17433adcba9aSMichal Krawczyk void ena_com_set_mmio_read_mode(struct ena_com_dev *ena_dev, bool readless_supported) 174499ecfbf8SJan Medala { 174599ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 174699ecfbf8SJan Medala 174799ecfbf8SJan Medala mmio_read->readless_supported = readless_supported; 174899ecfbf8SJan Medala } 174999ecfbf8SJan Medala 175099ecfbf8SJan Medala void ena_com_mmio_reg_read_request_destroy(struct ena_com_dev *ena_dev) 175199ecfbf8SJan Medala { 175299ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 175399ecfbf8SJan Medala 17543adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, 0x0, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_LO_OFF); 17553adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, 0x0, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_HI_OFF); 175699ecfbf8SJan Medala 175799ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 175899ecfbf8SJan Medala sizeof(*mmio_read->read_resp), 175999ecfbf8SJan Medala mmio_read->read_resp, 176099ecfbf8SJan Medala mmio_read->read_resp_dma_addr, 176199ecfbf8SJan Medala mmio_read->read_resp_mem_handle); 176299ecfbf8SJan Medala 176399ecfbf8SJan Medala mmio_read->read_resp = NULL; 1764b68309beSRafal Kozik ENA_SPINLOCK_DESTROY(mmio_read->lock); 176599ecfbf8SJan Medala } 176699ecfbf8SJan Medala 176799ecfbf8SJan Medala void ena_com_mmio_reg_read_request_write_dev_addr(struct ena_com_dev *ena_dev) 176899ecfbf8SJan Medala { 176999ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 177099ecfbf8SJan Medala u32 addr_low, addr_high; 177199ecfbf8SJan Medala 177299ecfbf8SJan Medala addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(mmio_read->read_resp_dma_addr); 177399ecfbf8SJan Medala addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(mmio_read->read_resp_dma_addr); 177499ecfbf8SJan Medala 17753adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_LO_OFF); 17763adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_HI_OFF); 177799ecfbf8SJan Medala } 177899ecfbf8SJan Medala 177999ecfbf8SJan Medala int ena_com_admin_init(struct ena_com_dev *ena_dev, 1780b68309beSRafal Kozik struct ena_aenq_handlers *aenq_handlers) 178199ecfbf8SJan Medala { 178299ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 178399ecfbf8SJan Medala u32 aq_caps, acq_caps, dev_sts, addr_low, addr_high; 178499ecfbf8SJan Medala int ret; 178599ecfbf8SJan Medala 178699ecfbf8SJan Medala dev_sts = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF); 178799ecfbf8SJan Medala 178899ecfbf8SJan Medala if (unlikely(dev_sts == ENA_MMIO_READ_TIMEOUT)) { 178999ecfbf8SJan Medala ena_trc_err("Reg read timeout occurred\n"); 179099ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 179199ecfbf8SJan Medala } 179299ecfbf8SJan Medala 179399ecfbf8SJan Medala if (!(dev_sts & ENA_REGS_DEV_STS_READY_MASK)) { 179499ecfbf8SJan Medala ena_trc_err("Device isn't ready, abort com init\n"); 17956dcee7cdSJan Medala return ENA_COM_NO_DEVICE; 179699ecfbf8SJan Medala } 179799ecfbf8SJan Medala 179899ecfbf8SJan Medala admin_queue->q_depth = ENA_ADMIN_QUEUE_DEPTH; 179999ecfbf8SJan Medala 1800b68309beSRafal Kozik admin_queue->bus = ena_dev->bus; 180199ecfbf8SJan Medala admin_queue->q_dmadev = ena_dev->dmadev; 180299ecfbf8SJan Medala admin_queue->polling = false; 180399ecfbf8SJan Medala admin_queue->curr_cmd_id = 0; 180499ecfbf8SJan Medala 180599ecfbf8SJan Medala ATOMIC32_SET(&admin_queue->outstanding_cmds, 0); 180699ecfbf8SJan Medala 180799ecfbf8SJan Medala ENA_SPINLOCK_INIT(admin_queue->q_lock); 180899ecfbf8SJan Medala 180999ecfbf8SJan Medala ret = ena_com_init_comp_ctxt(admin_queue); 181099ecfbf8SJan Medala if (ret) 181199ecfbf8SJan Medala goto error; 181299ecfbf8SJan Medala 181399ecfbf8SJan Medala ret = ena_com_admin_init_sq(admin_queue); 181499ecfbf8SJan Medala if (ret) 181599ecfbf8SJan Medala goto error; 181699ecfbf8SJan Medala 181799ecfbf8SJan Medala ret = ena_com_admin_init_cq(admin_queue); 181899ecfbf8SJan Medala if (ret) 181999ecfbf8SJan Medala goto error; 182099ecfbf8SJan Medala 18213adcba9aSMichal Krawczyk admin_queue->sq.db_addr = (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 18223adcba9aSMichal Krawczyk ENA_REGS_AQ_DB_OFF); 182399ecfbf8SJan Medala 182499ecfbf8SJan Medala addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(admin_queue->sq.dma_addr); 182599ecfbf8SJan Medala addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(admin_queue->sq.dma_addr); 182699ecfbf8SJan Medala 18273adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_AQ_BASE_LO_OFF); 18283adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_AQ_BASE_HI_OFF); 182999ecfbf8SJan Medala 183099ecfbf8SJan Medala addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(admin_queue->cq.dma_addr); 183199ecfbf8SJan Medala addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(admin_queue->cq.dma_addr); 183299ecfbf8SJan Medala 18333adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_ACQ_BASE_LO_OFF); 18343adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_ACQ_BASE_HI_OFF); 183599ecfbf8SJan Medala 183699ecfbf8SJan Medala aq_caps = 0; 183799ecfbf8SJan Medala aq_caps |= admin_queue->q_depth & ENA_REGS_AQ_CAPS_AQ_DEPTH_MASK; 183899ecfbf8SJan Medala aq_caps |= (sizeof(struct ena_admin_aq_entry) << 183999ecfbf8SJan Medala ENA_REGS_AQ_CAPS_AQ_ENTRY_SIZE_SHIFT) & 184099ecfbf8SJan Medala ENA_REGS_AQ_CAPS_AQ_ENTRY_SIZE_MASK; 184199ecfbf8SJan Medala 184299ecfbf8SJan Medala acq_caps = 0; 184399ecfbf8SJan Medala acq_caps |= admin_queue->q_depth & ENA_REGS_ACQ_CAPS_ACQ_DEPTH_MASK; 184499ecfbf8SJan Medala acq_caps |= (sizeof(struct ena_admin_acq_entry) << 184599ecfbf8SJan Medala ENA_REGS_ACQ_CAPS_ACQ_ENTRY_SIZE_SHIFT) & 184699ecfbf8SJan Medala ENA_REGS_ACQ_CAPS_ACQ_ENTRY_SIZE_MASK; 184799ecfbf8SJan Medala 18483adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, aq_caps, ena_dev->reg_bar + ENA_REGS_AQ_CAPS_OFF); 18493adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, acq_caps, ena_dev->reg_bar + ENA_REGS_ACQ_CAPS_OFF); 185099ecfbf8SJan Medala ret = ena_com_admin_init_aenq(ena_dev, aenq_handlers); 185199ecfbf8SJan Medala if (ret) 185299ecfbf8SJan Medala goto error; 185399ecfbf8SJan Medala 18540c84e048SMichal Krawczyk admin_queue->ena_dev = ena_dev; 185599ecfbf8SJan Medala admin_queue->running_state = true; 185699ecfbf8SJan Medala 185799ecfbf8SJan Medala return 0; 185899ecfbf8SJan Medala error: 185999ecfbf8SJan Medala ena_com_admin_destroy(ena_dev); 186099ecfbf8SJan Medala 186199ecfbf8SJan Medala return ret; 186299ecfbf8SJan Medala } 186399ecfbf8SJan Medala 186499ecfbf8SJan Medala int ena_com_create_io_queue(struct ena_com_dev *ena_dev, 18656dcee7cdSJan Medala struct ena_com_create_io_ctx *ctx) 186699ecfbf8SJan Medala { 186799ecfbf8SJan Medala struct ena_com_io_sq *io_sq; 186899ecfbf8SJan Medala struct ena_com_io_cq *io_cq; 18693adcba9aSMichal Krawczyk int ret; 187099ecfbf8SJan Medala 18716dcee7cdSJan Medala if (ctx->qid >= ENA_TOTAL_NUM_QUEUES) { 187299ecfbf8SJan Medala ena_trc_err("Qid (%d) is bigger than max num of queues (%d)\n", 18736dcee7cdSJan Medala ctx->qid, ENA_TOTAL_NUM_QUEUES); 187499ecfbf8SJan Medala return ENA_COM_INVAL; 187599ecfbf8SJan Medala } 187699ecfbf8SJan Medala 18776dcee7cdSJan Medala io_sq = &ena_dev->io_sq_queues[ctx->qid]; 18786dcee7cdSJan Medala io_cq = &ena_dev->io_cq_queues[ctx->qid]; 187999ecfbf8SJan Medala 18803adcba9aSMichal Krawczyk memset(io_sq, 0x0, sizeof(*io_sq)); 18813adcba9aSMichal Krawczyk memset(io_cq, 0x0, sizeof(*io_cq)); 188299ecfbf8SJan Medala 188399ecfbf8SJan Medala /* Init CQ */ 18846dcee7cdSJan Medala io_cq->q_depth = ctx->queue_size; 18856dcee7cdSJan Medala io_cq->direction = ctx->direction; 18866dcee7cdSJan Medala io_cq->qid = ctx->qid; 188799ecfbf8SJan Medala 18886dcee7cdSJan Medala io_cq->msix_vector = ctx->msix_vector; 188999ecfbf8SJan Medala 18906dcee7cdSJan Medala io_sq->q_depth = ctx->queue_size; 18916dcee7cdSJan Medala io_sq->direction = ctx->direction; 18926dcee7cdSJan Medala io_sq->qid = ctx->qid; 189399ecfbf8SJan Medala 18946dcee7cdSJan Medala io_sq->mem_queue_type = ctx->mem_queue_type; 189599ecfbf8SJan Medala 18966dcee7cdSJan Medala if (ctx->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) 189799ecfbf8SJan Medala /* header length is limited to 8 bits */ 189899ecfbf8SJan Medala io_sq->tx_max_header_size = 18996dcee7cdSJan Medala ENA_MIN32(ena_dev->tx_max_header_size, SZ_256); 190099ecfbf8SJan Medala 19016dcee7cdSJan Medala ret = ena_com_init_io_sq(ena_dev, ctx, io_sq); 190299ecfbf8SJan Medala if (ret) 190399ecfbf8SJan Medala goto error; 19046dcee7cdSJan Medala ret = ena_com_init_io_cq(ena_dev, ctx, io_cq); 190599ecfbf8SJan Medala if (ret) 190699ecfbf8SJan Medala goto error; 190799ecfbf8SJan Medala 190899ecfbf8SJan Medala ret = ena_com_create_io_cq(ena_dev, io_cq); 190999ecfbf8SJan Medala if (ret) 191099ecfbf8SJan Medala goto error; 191199ecfbf8SJan Medala 191299ecfbf8SJan Medala ret = ena_com_create_io_sq(ena_dev, io_sq, io_cq->idx); 191399ecfbf8SJan Medala if (ret) 191499ecfbf8SJan Medala goto destroy_io_cq; 191599ecfbf8SJan Medala 191699ecfbf8SJan Medala return 0; 191799ecfbf8SJan Medala 191899ecfbf8SJan Medala destroy_io_cq: 191999ecfbf8SJan Medala ena_com_destroy_io_cq(ena_dev, io_cq); 192099ecfbf8SJan Medala error: 192199ecfbf8SJan Medala ena_com_io_queue_free(ena_dev, io_sq, io_cq); 192299ecfbf8SJan Medala return ret; 192399ecfbf8SJan Medala } 192499ecfbf8SJan Medala 192599ecfbf8SJan Medala void ena_com_destroy_io_queue(struct ena_com_dev *ena_dev, u16 qid) 192699ecfbf8SJan Medala { 192799ecfbf8SJan Medala struct ena_com_io_sq *io_sq; 192899ecfbf8SJan Medala struct ena_com_io_cq *io_cq; 192999ecfbf8SJan Medala 193099ecfbf8SJan Medala if (qid >= ENA_TOTAL_NUM_QUEUES) { 193199ecfbf8SJan Medala ena_trc_err("Qid (%d) is bigger than max num of queues (%d)\n", 193299ecfbf8SJan Medala qid, ENA_TOTAL_NUM_QUEUES); 193399ecfbf8SJan Medala return; 193499ecfbf8SJan Medala } 193599ecfbf8SJan Medala 193699ecfbf8SJan Medala io_sq = &ena_dev->io_sq_queues[qid]; 193799ecfbf8SJan Medala io_cq = &ena_dev->io_cq_queues[qid]; 193899ecfbf8SJan Medala 193999ecfbf8SJan Medala ena_com_destroy_io_sq(ena_dev, io_sq); 194099ecfbf8SJan Medala ena_com_destroy_io_cq(ena_dev, io_cq); 194199ecfbf8SJan Medala 194299ecfbf8SJan Medala ena_com_io_queue_free(ena_dev, io_sq, io_cq); 194399ecfbf8SJan Medala } 194499ecfbf8SJan Medala 194599ecfbf8SJan Medala int ena_com_get_link_params(struct ena_com_dev *ena_dev, 194699ecfbf8SJan Medala struct ena_admin_get_feat_resp *resp) 194799ecfbf8SJan Medala { 1948b68309beSRafal Kozik return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG, 0); 1949b68309beSRafal Kozik } 1950b68309beSRafal Kozik 195199ecfbf8SJan Medala int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev, 195299ecfbf8SJan Medala struct ena_com_dev_get_features_ctx *get_feat_ctx) 195399ecfbf8SJan Medala { 195499ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 195599ecfbf8SJan Medala int rc; 195699ecfbf8SJan Medala 195799ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 1958b68309beSRafal Kozik ENA_ADMIN_DEVICE_ATTRIBUTES, 0); 195999ecfbf8SJan Medala if (rc) 196099ecfbf8SJan Medala return rc; 196199ecfbf8SJan Medala 196299ecfbf8SJan Medala memcpy(&get_feat_ctx->dev_attr, &get_resp.u.dev_attr, 196399ecfbf8SJan Medala sizeof(get_resp.u.dev_attr)); 196499ecfbf8SJan Medala ena_dev->supported_features = get_resp.u.dev_attr.supported_features; 196599ecfbf8SJan Medala 1966b68309beSRafal Kozik if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 196799ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 1968b68309beSRafal Kozik ENA_ADMIN_MAX_QUEUES_EXT, 1969b68309beSRafal Kozik ENA_FEATURE_MAX_QUEUE_EXT_VER); 197099ecfbf8SJan Medala if (rc) 197199ecfbf8SJan Medala return rc; 197299ecfbf8SJan Medala 1973b68309beSRafal Kozik if (get_resp.u.max_queue_ext.version != ENA_FEATURE_MAX_QUEUE_EXT_VER) 1974b68309beSRafal Kozik return -EINVAL; 1975b68309beSRafal Kozik 1976b68309beSRafal Kozik memcpy(&get_feat_ctx->max_queue_ext, &get_resp.u.max_queue_ext, 1977b68309beSRafal Kozik sizeof(get_resp.u.max_queue_ext)); 1978b68309beSRafal Kozik ena_dev->tx_max_header_size = 1979b68309beSRafal Kozik get_resp.u.max_queue_ext.max_queue_ext.max_tx_header_size; 1980b68309beSRafal Kozik } else { 1981b68309beSRafal Kozik rc = ena_com_get_feature(ena_dev, &get_resp, 1982b68309beSRafal Kozik ENA_ADMIN_MAX_QUEUES_NUM, 0); 198399ecfbf8SJan Medala memcpy(&get_feat_ctx->max_queues, &get_resp.u.max_queue, 198499ecfbf8SJan Medala sizeof(get_resp.u.max_queue)); 1985b68309beSRafal Kozik ena_dev->tx_max_header_size = 1986b68309beSRafal Kozik get_resp.u.max_queue.max_header_size; 1987b68309beSRafal Kozik 1988b68309beSRafal Kozik if (rc) 1989b68309beSRafal Kozik return rc; 1990b68309beSRafal Kozik } 199199ecfbf8SJan Medala 199299ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 1993b68309beSRafal Kozik ENA_ADMIN_AENQ_CONFIG, 0); 199499ecfbf8SJan Medala if (rc) 199599ecfbf8SJan Medala return rc; 199699ecfbf8SJan Medala 199799ecfbf8SJan Medala memcpy(&get_feat_ctx->aenq, &get_resp.u.aenq, 199899ecfbf8SJan Medala sizeof(get_resp.u.aenq)); 199999ecfbf8SJan Medala 200099ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 2001b68309beSRafal Kozik ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0); 200299ecfbf8SJan Medala if (rc) 200399ecfbf8SJan Medala return rc; 200499ecfbf8SJan Medala 200599ecfbf8SJan Medala memcpy(&get_feat_ctx->offload, &get_resp.u.offload, 200699ecfbf8SJan Medala sizeof(get_resp.u.offload)); 200799ecfbf8SJan Medala 20083adcba9aSMichal Krawczyk /* Driver hints isn't mandatory admin command. So in case the 20093adcba9aSMichal Krawczyk * command isn't supported set driver hints to 0 20103adcba9aSMichal Krawczyk */ 2011b68309beSRafal Kozik rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_HW_HINTS, 0); 20123adcba9aSMichal Krawczyk 20133adcba9aSMichal Krawczyk if (!rc) 20143adcba9aSMichal Krawczyk memcpy(&get_feat_ctx->hw_hints, &get_resp.u.hw_hints, 20153adcba9aSMichal Krawczyk sizeof(get_resp.u.hw_hints)); 20163adcba9aSMichal Krawczyk else if (rc == ENA_COM_UNSUPPORTED) 20173adcba9aSMichal Krawczyk memset(&get_feat_ctx->hw_hints, 0x0, sizeof(get_feat_ctx->hw_hints)); 20183adcba9aSMichal Krawczyk else 20193adcba9aSMichal Krawczyk return rc; 20203adcba9aSMichal Krawczyk 2021b68309beSRafal Kozik rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_LLQ, 0); 2022b68309beSRafal Kozik if (!rc) 2023b68309beSRafal Kozik memcpy(&get_feat_ctx->llq, &get_resp.u.llq, 2024b68309beSRafal Kozik sizeof(get_resp.u.llq)); 2025b68309beSRafal Kozik else if (rc == ENA_COM_UNSUPPORTED) 2026b68309beSRafal Kozik memset(&get_feat_ctx->llq, 0x0, sizeof(get_feat_ctx->llq)); 2027b68309beSRafal Kozik else 2028b68309beSRafal Kozik return rc; 2029b68309beSRafal Kozik 2030b68309beSRafal Kozik rc = ena_com_get_feature(ena_dev, &get_resp, 2031b68309beSRafal Kozik ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG, 0); 2032b68309beSRafal Kozik if (!rc) 2033b68309beSRafal Kozik memcpy(&get_feat_ctx->ind_table, &get_resp.u.ind_table, 2034b68309beSRafal Kozik sizeof(get_resp.u.ind_table)); 2035b68309beSRafal Kozik else if (rc == ENA_COM_UNSUPPORTED) 2036b68309beSRafal Kozik memset(&get_feat_ctx->ind_table, 0x0, 2037b68309beSRafal Kozik sizeof(get_feat_ctx->ind_table)); 2038b68309beSRafal Kozik else 2039b68309beSRafal Kozik return rc; 2040b68309beSRafal Kozik 204199ecfbf8SJan Medala return 0; 204299ecfbf8SJan Medala } 204399ecfbf8SJan Medala 204499ecfbf8SJan Medala void ena_com_admin_q_comp_intr_handler(struct ena_com_dev *ena_dev) 204599ecfbf8SJan Medala { 204699ecfbf8SJan Medala ena_com_handle_admin_completion(&ena_dev->admin_queue); 204799ecfbf8SJan Medala } 204899ecfbf8SJan Medala 204999ecfbf8SJan Medala /* ena_handle_specific_aenq_event: 205099ecfbf8SJan Medala * return the handler that is relevant to the specific event group 205199ecfbf8SJan Medala */ 205299ecfbf8SJan Medala static ena_aenq_handler ena_com_get_specific_aenq_cb(struct ena_com_dev *dev, 205399ecfbf8SJan Medala u16 group) 205499ecfbf8SJan Medala { 205599ecfbf8SJan Medala struct ena_aenq_handlers *aenq_handlers = dev->aenq.aenq_handlers; 205699ecfbf8SJan Medala 205799ecfbf8SJan Medala if ((group < ENA_MAX_HANDLERS) && aenq_handlers->handlers[group]) 205899ecfbf8SJan Medala return aenq_handlers->handlers[group]; 205999ecfbf8SJan Medala 206099ecfbf8SJan Medala return aenq_handlers->unimplemented_handler; 206199ecfbf8SJan Medala } 206299ecfbf8SJan Medala 206399ecfbf8SJan Medala /* ena_aenq_intr_handler: 206499ecfbf8SJan Medala * handles the aenq incoming events. 206599ecfbf8SJan Medala * pop events from the queue and apply the specific handler 206699ecfbf8SJan Medala */ 206799ecfbf8SJan Medala void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data) 206899ecfbf8SJan Medala { 206999ecfbf8SJan Medala struct ena_admin_aenq_entry *aenq_e; 207099ecfbf8SJan Medala struct ena_admin_aenq_common_desc *aenq_common; 207199ecfbf8SJan Medala struct ena_com_aenq *aenq = &dev->aenq; 2072b2b02edeSMichal Krawczyk u64 timestamp; 2073b68309beSRafal Kozik ena_aenq_handler handler_cb; 207499ecfbf8SJan Medala u16 masked_head, processed = 0; 207599ecfbf8SJan Medala u8 phase; 207699ecfbf8SJan Medala 207799ecfbf8SJan Medala masked_head = aenq->head & (aenq->q_depth - 1); 207899ecfbf8SJan Medala phase = aenq->phase; 207999ecfbf8SJan Medala aenq_e = &aenq->entries[masked_head]; /* Get first entry */ 208099ecfbf8SJan Medala aenq_common = &aenq_e->aenq_common_desc; 208199ecfbf8SJan Medala 208299ecfbf8SJan Medala /* Go over all the events */ 2083b68309beSRafal Kozik while ((READ_ONCE8(aenq_common->flags) & 2084b68309beSRafal Kozik ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK) == phase) { 2085b68309beSRafal Kozik /* Make sure the phase bit (ownership) is as expected before 2086b68309beSRafal Kozik * reading the rest of the descriptor. 2087b68309beSRafal Kozik */ 2088b68309beSRafal Kozik dma_rmb(); 2089b68309beSRafal Kozik 2090b2b02edeSMichal Krawczyk timestamp = (u64)aenq_common->timestamp_low | 2091b2b02edeSMichal Krawczyk ((u64)aenq_common->timestamp_high << 32); 20923adcba9aSMichal Krawczyk ENA_TOUCH(timestamp); /* In case debug is disabled */ 2093422397c5SMichal Krawczyk ena_trc_dbg("AENQ! Group[%x] Syndrom[%x] timestamp: [%" ENA_PRIu64 "s]\n", 209499ecfbf8SJan Medala aenq_common->group, 209599ecfbf8SJan Medala aenq_common->syndrom, 20963adcba9aSMichal Krawczyk timestamp); 209799ecfbf8SJan Medala 209899ecfbf8SJan Medala /* Handle specific event*/ 209999ecfbf8SJan Medala handler_cb = ena_com_get_specific_aenq_cb(dev, 210099ecfbf8SJan Medala aenq_common->group); 210199ecfbf8SJan Medala handler_cb(data, aenq_e); /* call the actual event handler*/ 210299ecfbf8SJan Medala 210399ecfbf8SJan Medala /* Get next event entry */ 210499ecfbf8SJan Medala masked_head++; 210599ecfbf8SJan Medala processed++; 210699ecfbf8SJan Medala 210799ecfbf8SJan Medala if (unlikely(masked_head == aenq->q_depth)) { 210899ecfbf8SJan Medala masked_head = 0; 210999ecfbf8SJan Medala phase = !phase; 211099ecfbf8SJan Medala } 211199ecfbf8SJan Medala aenq_e = &aenq->entries[masked_head]; 211299ecfbf8SJan Medala aenq_common = &aenq_e->aenq_common_desc; 211399ecfbf8SJan Medala } 211499ecfbf8SJan Medala 211599ecfbf8SJan Medala aenq->head += processed; 211699ecfbf8SJan Medala aenq->phase = phase; 211799ecfbf8SJan Medala 211899ecfbf8SJan Medala /* Don't update aenq doorbell if there weren't any processed events */ 211999ecfbf8SJan Medala if (!processed) 212099ecfbf8SJan Medala return; 212199ecfbf8SJan Medala 212299ecfbf8SJan Medala /* write the aenq doorbell after all AENQ descriptors were read */ 212399ecfbf8SJan Medala mb(); 2124b68309beSRafal Kozik ENA_REG_WRITE32_RELAXED(dev->bus, (u32)aenq->head, 2125b68309beSRafal Kozik dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF); 2126b68309beSRafal Kozik mmiowb(); 212799ecfbf8SJan Medala } 212899ecfbf8SJan Medala 21293adcba9aSMichal Krawczyk int ena_com_dev_reset(struct ena_com_dev *ena_dev, 21303adcba9aSMichal Krawczyk enum ena_regs_reset_reason_types reset_reason) 213199ecfbf8SJan Medala { 213299ecfbf8SJan Medala u32 stat, timeout, cap, reset_val; 213399ecfbf8SJan Medala int rc; 213499ecfbf8SJan Medala 213599ecfbf8SJan Medala stat = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF); 213699ecfbf8SJan Medala cap = ena_com_reg_bar_read32(ena_dev, ENA_REGS_CAPS_OFF); 213799ecfbf8SJan Medala 213899ecfbf8SJan Medala if (unlikely((stat == ENA_MMIO_READ_TIMEOUT) || 213999ecfbf8SJan Medala (cap == ENA_MMIO_READ_TIMEOUT))) { 214099ecfbf8SJan Medala ena_trc_err("Reg read32 timeout occurred\n"); 214199ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 214299ecfbf8SJan Medala } 214399ecfbf8SJan Medala 214499ecfbf8SJan Medala if ((stat & ENA_REGS_DEV_STS_READY_MASK) == 0) { 214599ecfbf8SJan Medala ena_trc_err("Device isn't ready, can't reset device\n"); 214699ecfbf8SJan Medala return ENA_COM_INVAL; 214799ecfbf8SJan Medala } 214899ecfbf8SJan Medala 214999ecfbf8SJan Medala timeout = (cap & ENA_REGS_CAPS_RESET_TIMEOUT_MASK) >> 215099ecfbf8SJan Medala ENA_REGS_CAPS_RESET_TIMEOUT_SHIFT; 215199ecfbf8SJan Medala if (timeout == 0) { 215299ecfbf8SJan Medala ena_trc_err("Invalid timeout value\n"); 215399ecfbf8SJan Medala return ENA_COM_INVAL; 215499ecfbf8SJan Medala } 215599ecfbf8SJan Medala 215699ecfbf8SJan Medala /* start reset */ 215799ecfbf8SJan Medala reset_val = ENA_REGS_DEV_CTL_DEV_RESET_MASK; 21583adcba9aSMichal Krawczyk reset_val |= (reset_reason << ENA_REGS_DEV_CTL_RESET_REASON_SHIFT) & 21593adcba9aSMichal Krawczyk ENA_REGS_DEV_CTL_RESET_REASON_MASK; 21603adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, reset_val, ena_dev->reg_bar + ENA_REGS_DEV_CTL_OFF); 216199ecfbf8SJan Medala 216299ecfbf8SJan Medala /* Write again the MMIO read request address */ 216399ecfbf8SJan Medala ena_com_mmio_reg_read_request_write_dev_addr(ena_dev); 216499ecfbf8SJan Medala 216599ecfbf8SJan Medala rc = wait_for_reset_state(ena_dev, timeout, 216699ecfbf8SJan Medala ENA_REGS_DEV_STS_RESET_IN_PROGRESS_MASK); 216799ecfbf8SJan Medala if (rc != 0) { 216899ecfbf8SJan Medala ena_trc_err("Reset indication didn't turn on\n"); 216999ecfbf8SJan Medala return rc; 217099ecfbf8SJan Medala } 217199ecfbf8SJan Medala 217299ecfbf8SJan Medala /* reset done */ 21733adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, 0, ena_dev->reg_bar + ENA_REGS_DEV_CTL_OFF); 217499ecfbf8SJan Medala rc = wait_for_reset_state(ena_dev, timeout, 0); 217599ecfbf8SJan Medala if (rc != 0) { 217699ecfbf8SJan Medala ena_trc_err("Reset indication didn't turn off\n"); 217799ecfbf8SJan Medala return rc; 217899ecfbf8SJan Medala } 217999ecfbf8SJan Medala 21803adcba9aSMichal Krawczyk timeout = (cap & ENA_REGS_CAPS_ADMIN_CMD_TO_MASK) >> 21813adcba9aSMichal Krawczyk ENA_REGS_CAPS_ADMIN_CMD_TO_SHIFT; 21823adcba9aSMichal Krawczyk if (timeout) 21833adcba9aSMichal Krawczyk /* the resolution of timeout reg is 100ms */ 21843adcba9aSMichal Krawczyk ena_dev->admin_queue.completion_timeout = timeout * 100000; 21853adcba9aSMichal Krawczyk else 21863adcba9aSMichal Krawczyk ena_dev->admin_queue.completion_timeout = ADMIN_CMD_TIMEOUT_US; 21873adcba9aSMichal Krawczyk 218899ecfbf8SJan Medala return 0; 218999ecfbf8SJan Medala } 219099ecfbf8SJan Medala 219199ecfbf8SJan Medala static int ena_get_dev_stats(struct ena_com_dev *ena_dev, 21923adcba9aSMichal Krawczyk struct ena_com_stats_ctx *ctx, 219399ecfbf8SJan Medala enum ena_admin_get_stats_type type) 219499ecfbf8SJan Medala { 21953adcba9aSMichal Krawczyk struct ena_admin_aq_get_stats_cmd *get_cmd = &ctx->get_cmd; 21963adcba9aSMichal Krawczyk struct ena_admin_acq_get_stats_resp *get_resp = &ctx->get_resp; 219799ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 21983adcba9aSMichal Krawczyk int ret; 219999ecfbf8SJan Medala 220099ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 220199ecfbf8SJan Medala 220299ecfbf8SJan Medala get_cmd->aq_common_descriptor.opcode = ENA_ADMIN_GET_STATS; 220399ecfbf8SJan Medala get_cmd->aq_common_descriptor.flags = 0; 220499ecfbf8SJan Medala get_cmd->type = type; 220599ecfbf8SJan Medala 22063adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 220799ecfbf8SJan Medala (struct ena_admin_aq_entry *)get_cmd, 220899ecfbf8SJan Medala sizeof(*get_cmd), 220999ecfbf8SJan Medala (struct ena_admin_acq_entry *)get_resp, 221099ecfbf8SJan Medala sizeof(*get_resp)); 221199ecfbf8SJan Medala 221299ecfbf8SJan Medala if (unlikely(ret)) 221399ecfbf8SJan Medala ena_trc_err("Failed to get stats. error: %d\n", ret); 221499ecfbf8SJan Medala 221599ecfbf8SJan Medala return ret; 221699ecfbf8SJan Medala } 221799ecfbf8SJan Medala 22180d09cbc7SMichal Krawczyk int ena_com_get_eni_stats(struct ena_com_dev *ena_dev, 22190d09cbc7SMichal Krawczyk struct ena_admin_eni_stats *stats) 22200d09cbc7SMichal Krawczyk { 22210d09cbc7SMichal Krawczyk struct ena_com_stats_ctx ctx; 22220d09cbc7SMichal Krawczyk int ret; 22230d09cbc7SMichal Krawczyk 22240d09cbc7SMichal Krawczyk memset(&ctx, 0x0, sizeof(ctx)); 22250d09cbc7SMichal Krawczyk ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENI); 22260d09cbc7SMichal Krawczyk if (likely(ret == 0)) 22270d09cbc7SMichal Krawczyk memcpy(stats, &ctx.get_resp.u.eni_stats, 22280d09cbc7SMichal Krawczyk sizeof(ctx.get_resp.u.eni_stats)); 22290d09cbc7SMichal Krawczyk 22300d09cbc7SMichal Krawczyk return ret; 22310d09cbc7SMichal Krawczyk } 22320d09cbc7SMichal Krawczyk 223399ecfbf8SJan Medala int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev, 223499ecfbf8SJan Medala struct ena_admin_basic_stats *stats) 223599ecfbf8SJan Medala { 22363adcba9aSMichal Krawczyk struct ena_com_stats_ctx ctx; 22373adcba9aSMichal Krawczyk int ret; 223899ecfbf8SJan Medala 22393adcba9aSMichal Krawczyk memset(&ctx, 0x0, sizeof(ctx)); 22403adcba9aSMichal Krawczyk ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_BASIC); 224199ecfbf8SJan Medala if (likely(ret == 0)) 22420d09cbc7SMichal Krawczyk memcpy(stats, &ctx.get_resp.u.basic_stats, 22430d09cbc7SMichal Krawczyk sizeof(ctx.get_resp.u.basic_stats)); 224499ecfbf8SJan Medala 224599ecfbf8SJan Medala return ret; 224699ecfbf8SJan Medala } 224799ecfbf8SJan Medala 224899ecfbf8SJan Medala int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, int mtu) 224999ecfbf8SJan Medala { 225099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 225199ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 225299ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 22533adcba9aSMichal Krawczyk int ret; 225499ecfbf8SJan Medala 225599ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_MTU)) { 22563adcba9aSMichal Krawczyk ena_trc_dbg("Feature %d isn't supported\n", ENA_ADMIN_MTU); 22573adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 225899ecfbf8SJan Medala } 225999ecfbf8SJan Medala 226099ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 226199ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 226299ecfbf8SJan Medala 226399ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 226499ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 0; 226599ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_MTU; 226699ecfbf8SJan Medala cmd.u.mtu.mtu = mtu; 226799ecfbf8SJan Medala 226899ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 226999ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 227099ecfbf8SJan Medala sizeof(cmd), 227199ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 227299ecfbf8SJan Medala sizeof(resp)); 227399ecfbf8SJan Medala 22743adcba9aSMichal Krawczyk if (unlikely(ret)) 227599ecfbf8SJan Medala ena_trc_err("Failed to set mtu %d. error: %d\n", mtu, ret); 22763adcba9aSMichal Krawczyk 22773adcba9aSMichal Krawczyk return ret; 227899ecfbf8SJan Medala } 227999ecfbf8SJan Medala 228099ecfbf8SJan Medala int ena_com_get_offload_settings(struct ena_com_dev *ena_dev, 228199ecfbf8SJan Medala struct ena_admin_feature_offload_desc *offload) 228299ecfbf8SJan Medala { 228399ecfbf8SJan Medala int ret; 228499ecfbf8SJan Medala struct ena_admin_get_feat_resp resp; 228599ecfbf8SJan Medala 228699ecfbf8SJan Medala ret = ena_com_get_feature(ena_dev, &resp, 2287b68309beSRafal Kozik ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0); 228899ecfbf8SJan Medala if (unlikely(ret)) { 228999ecfbf8SJan Medala ena_trc_err("Failed to get offload capabilities %d\n", ret); 22903adcba9aSMichal Krawczyk return ret; 229199ecfbf8SJan Medala } 229299ecfbf8SJan Medala 229399ecfbf8SJan Medala memcpy(offload, &resp.u.offload, sizeof(resp.u.offload)); 229499ecfbf8SJan Medala 229599ecfbf8SJan Medala return 0; 229699ecfbf8SJan Medala } 229799ecfbf8SJan Medala 229899ecfbf8SJan Medala int ena_com_set_hash_function(struct ena_com_dev *ena_dev) 229999ecfbf8SJan Medala { 230099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 230199ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 230299ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 230399ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 230499ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 230599ecfbf8SJan Medala int ret; 230699ecfbf8SJan Medala 230799ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, 230899ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION)) { 23093adcba9aSMichal Krawczyk ena_trc_dbg("Feature %d isn't supported\n", 231099ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION); 23113adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 231299ecfbf8SJan Medala } 231399ecfbf8SJan Medala 231499ecfbf8SJan Medala /* Validate hash function is supported */ 231599ecfbf8SJan Medala ret = ena_com_get_feature(ena_dev, &get_resp, 2316b68309beSRafal Kozik ENA_ADMIN_RSS_HASH_FUNCTION, 0); 231799ecfbf8SJan Medala if (unlikely(ret)) 231899ecfbf8SJan Medala return ret; 231999ecfbf8SJan Medala 2320b2b02edeSMichal Krawczyk if (!(get_resp.u.flow_hash_func.supported_func & BIT(rss->hash_func))) { 232199ecfbf8SJan Medala ena_trc_err("Func hash %d isn't supported by device, abort\n", 232299ecfbf8SJan Medala rss->hash_func); 23233adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 232499ecfbf8SJan Medala } 232599ecfbf8SJan Medala 232699ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 232799ecfbf8SJan Medala 232899ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 232999ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 233099ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 233199ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_RSS_HASH_FUNCTION; 233299ecfbf8SJan Medala cmd.u.flow_hash_func.init_val = rss->hash_init_val; 233399ecfbf8SJan Medala cmd.u.flow_hash_func.selected_func = 1 << rss->hash_func; 233499ecfbf8SJan Medala 233599ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 233699ecfbf8SJan Medala &cmd.control_buffer.address, 233799ecfbf8SJan Medala rss->hash_key_dma_addr); 233899ecfbf8SJan Medala if (unlikely(ret)) { 233999ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 234099ecfbf8SJan Medala return ret; 234199ecfbf8SJan Medala } 234299ecfbf8SJan Medala 234399ecfbf8SJan Medala cmd.control_buffer.length = sizeof(*rss->hash_key); 234499ecfbf8SJan Medala 234599ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 234699ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 234799ecfbf8SJan Medala sizeof(cmd), 234899ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 234999ecfbf8SJan Medala sizeof(resp)); 235099ecfbf8SJan Medala if (unlikely(ret)) { 235199ecfbf8SJan Medala ena_trc_err("Failed to set hash function %d. error: %d\n", 235299ecfbf8SJan Medala rss->hash_func, ret); 235399ecfbf8SJan Medala return ENA_COM_INVAL; 235499ecfbf8SJan Medala } 235599ecfbf8SJan Medala 235699ecfbf8SJan Medala return 0; 235799ecfbf8SJan Medala } 235899ecfbf8SJan Medala 235999ecfbf8SJan Medala int ena_com_fill_hash_function(struct ena_com_dev *ena_dev, 236099ecfbf8SJan Medala enum ena_admin_hash_functions func, 236199ecfbf8SJan Medala const u8 *key, u16 key_len, u32 init_val) 236299ecfbf8SJan Medala { 23636e585db6SMichal Krawczyk struct ena_admin_feature_rss_flow_hash_control *hash_key; 236499ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 23656e585db6SMichal Krawczyk enum ena_admin_hash_functions old_func; 23666e585db6SMichal Krawczyk struct ena_rss *rss = &ena_dev->rss; 236799ecfbf8SJan Medala int rc; 236899ecfbf8SJan Medala 23696e585db6SMichal Krawczyk hash_key = rss->hash_key; 23706e585db6SMichal Krawczyk 237199ecfbf8SJan Medala /* Make sure size is a mult of DWs */ 237299ecfbf8SJan Medala if (unlikely(key_len & 0x3)) 237399ecfbf8SJan Medala return ENA_COM_INVAL; 237499ecfbf8SJan Medala 237599ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 237699ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION, 237799ecfbf8SJan Medala rss->hash_key_dma_addr, 2378b68309beSRafal Kozik sizeof(*rss->hash_key), 0); 237999ecfbf8SJan Medala if (unlikely(rc)) 238099ecfbf8SJan Medala return rc; 238199ecfbf8SJan Medala 23826e585db6SMichal Krawczyk if (!(BIT(func) & get_resp.u.flow_hash_func.supported_func)) { 238399ecfbf8SJan Medala ena_trc_err("Flow hash function %d isn't supported\n", func); 23843adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 238599ecfbf8SJan Medala } 238699ecfbf8SJan Medala 238799ecfbf8SJan Medala switch (func) { 238899ecfbf8SJan Medala case ENA_ADMIN_TOEPLITZ: 2389086c6b66SMichal Krawczyk if (key) { 2390086c6b66SMichal Krawczyk if (key_len != sizeof(hash_key->key)) { 2391086c6b66SMichal Krawczyk ena_trc_err("key len (%hu) doesn't equal the supported size (%zu)\n", 239299ecfbf8SJan Medala key_len, sizeof(hash_key->key)); 239399ecfbf8SJan Medala return ENA_COM_INVAL; 239499ecfbf8SJan Medala } 239599ecfbf8SJan Medala memcpy(hash_key->key, key, key_len); 239699ecfbf8SJan Medala rss->hash_init_val = init_val; 2397086c6b66SMichal Krawczyk hash_key->keys_num = key_len / sizeof(u32); 2398086c6b66SMichal Krawczyk } 239999ecfbf8SJan Medala break; 240099ecfbf8SJan Medala case ENA_ADMIN_CRC32: 240199ecfbf8SJan Medala rss->hash_init_val = init_val; 240299ecfbf8SJan Medala break; 240399ecfbf8SJan Medala default: 240499ecfbf8SJan Medala ena_trc_err("Invalid hash function (%d)\n", func); 240599ecfbf8SJan Medala return ENA_COM_INVAL; 240699ecfbf8SJan Medala } 240799ecfbf8SJan Medala 24086e585db6SMichal Krawczyk old_func = rss->hash_func; 2409b2b02edeSMichal Krawczyk rss->hash_func = func; 241099ecfbf8SJan Medala rc = ena_com_set_hash_function(ena_dev); 241199ecfbf8SJan Medala 241299ecfbf8SJan Medala /* Restore the old function */ 241399ecfbf8SJan Medala if (unlikely(rc)) 24146e585db6SMichal Krawczyk rss->hash_func = old_func; 241599ecfbf8SJan Medala 241699ecfbf8SJan Medala return rc; 241799ecfbf8SJan Medala } 241899ecfbf8SJan Medala 241999ecfbf8SJan Medala int ena_com_get_hash_function(struct ena_com_dev *ena_dev, 24203e55684eSMichal Krawczyk enum ena_admin_hash_functions *func) 242199ecfbf8SJan Medala { 242299ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 242399ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 242499ecfbf8SJan Medala int rc; 242599ecfbf8SJan Medala 24263e55684eSMichal Krawczyk if (unlikely(!func)) 24273e55684eSMichal Krawczyk return ENA_COM_INVAL; 24283e55684eSMichal Krawczyk 242999ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 243099ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION, 243199ecfbf8SJan Medala rss->hash_key_dma_addr, 2432b68309beSRafal Kozik sizeof(*rss->hash_key), 0); 243399ecfbf8SJan Medala if (unlikely(rc)) 243499ecfbf8SJan Medala return rc; 243599ecfbf8SJan Medala 24363e55684eSMichal Krawczyk /* ENA_FFS() returns 1 in case the lsb is set */ 24376e585db6SMichal Krawczyk rss->hash_func = ENA_FFS(get_resp.u.flow_hash_func.selected_func); 24386e585db6SMichal Krawczyk if (rss->hash_func) 24396e585db6SMichal Krawczyk rss->hash_func--; 24406e585db6SMichal Krawczyk 244199ecfbf8SJan Medala *func = rss->hash_func; 244299ecfbf8SJan Medala 24433e55684eSMichal Krawczyk return 0; 24443e55684eSMichal Krawczyk } 24453e55684eSMichal Krawczyk 24463e55684eSMichal Krawczyk int ena_com_get_hash_key(struct ena_com_dev *ena_dev, u8 *key) 24473e55684eSMichal Krawczyk { 24483e55684eSMichal Krawczyk struct ena_admin_feature_rss_flow_hash_control *hash_key = 24493e55684eSMichal Krawczyk ena_dev->rss.hash_key; 24503e55684eSMichal Krawczyk 245199ecfbf8SJan Medala if (key) 24526dcee7cdSJan Medala memcpy(key, hash_key->key, (size_t)(hash_key->keys_num) << 2); 245399ecfbf8SJan Medala 245499ecfbf8SJan Medala return 0; 245599ecfbf8SJan Medala } 245699ecfbf8SJan Medala 245799ecfbf8SJan Medala int ena_com_get_hash_ctrl(struct ena_com_dev *ena_dev, 245899ecfbf8SJan Medala enum ena_admin_flow_hash_proto proto, 245999ecfbf8SJan Medala u16 *fields) 246099ecfbf8SJan Medala { 246199ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 246299ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 246399ecfbf8SJan Medala int rc; 246499ecfbf8SJan Medala 246599ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 246699ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_INPUT, 246799ecfbf8SJan Medala rss->hash_ctrl_dma_addr, 2468b68309beSRafal Kozik sizeof(*rss->hash_ctrl), 0); 246999ecfbf8SJan Medala if (unlikely(rc)) 247099ecfbf8SJan Medala return rc; 247199ecfbf8SJan Medala 247299ecfbf8SJan Medala if (fields) 247399ecfbf8SJan Medala *fields = rss->hash_ctrl->selected_fields[proto].fields; 247499ecfbf8SJan Medala 247599ecfbf8SJan Medala return 0; 247699ecfbf8SJan Medala } 247799ecfbf8SJan Medala 247899ecfbf8SJan Medala int ena_com_set_hash_ctrl(struct ena_com_dev *ena_dev) 247999ecfbf8SJan Medala { 248099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 248199ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 24823adcba9aSMichal Krawczyk struct ena_admin_feature_rss_hash_control *hash_ctrl = rss->hash_ctrl; 248399ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 248499ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 248599ecfbf8SJan Medala int ret; 248699ecfbf8SJan Medala 248799ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, 248899ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_INPUT)) { 24893adcba9aSMichal Krawczyk ena_trc_dbg("Feature %d isn't supported\n", 249099ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_INPUT); 24913adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 249299ecfbf8SJan Medala } 249399ecfbf8SJan Medala 24943adcba9aSMichal Krawczyk memset(&cmd, 0x0, sizeof(cmd)); 24953adcba9aSMichal Krawczyk 249699ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 249799ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 249899ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 249999ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_RSS_HASH_INPUT; 250099ecfbf8SJan Medala cmd.u.flow_hash_input.enabled_input_sort = 250199ecfbf8SJan Medala ENA_ADMIN_FEATURE_RSS_FLOW_HASH_INPUT_L3_SORT_MASK | 250299ecfbf8SJan Medala ENA_ADMIN_FEATURE_RSS_FLOW_HASH_INPUT_L4_SORT_MASK; 250399ecfbf8SJan Medala 250499ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 250599ecfbf8SJan Medala &cmd.control_buffer.address, 250699ecfbf8SJan Medala rss->hash_ctrl_dma_addr); 250799ecfbf8SJan Medala if (unlikely(ret)) { 250899ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 250999ecfbf8SJan Medala return ret; 251099ecfbf8SJan Medala } 25113adcba9aSMichal Krawczyk cmd.control_buffer.length = sizeof(*hash_ctrl); 251299ecfbf8SJan Medala 251399ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 251499ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 251599ecfbf8SJan Medala sizeof(cmd), 251699ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 251799ecfbf8SJan Medala sizeof(resp)); 25183adcba9aSMichal Krawczyk if (unlikely(ret)) 251999ecfbf8SJan Medala ena_trc_err("Failed to set hash input. error: %d\n", ret); 252099ecfbf8SJan Medala 25213adcba9aSMichal Krawczyk return ret; 252299ecfbf8SJan Medala } 252399ecfbf8SJan Medala 252499ecfbf8SJan Medala int ena_com_set_default_hash_ctrl(struct ena_com_dev *ena_dev) 252599ecfbf8SJan Medala { 252699ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 252799ecfbf8SJan Medala struct ena_admin_feature_rss_hash_control *hash_ctrl = 252899ecfbf8SJan Medala rss->hash_ctrl; 252999ecfbf8SJan Medala u16 available_fields = 0; 253099ecfbf8SJan Medala int rc, i; 253199ecfbf8SJan Medala 253299ecfbf8SJan Medala /* Get the supported hash input */ 25333adcba9aSMichal Krawczyk rc = ena_com_get_hash_ctrl(ena_dev, 0, NULL); 253499ecfbf8SJan Medala if (unlikely(rc)) 253599ecfbf8SJan Medala return rc; 253699ecfbf8SJan Medala 253799ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_TCP4].fields = 253899ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 253999ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 254099ecfbf8SJan Medala 254199ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_UDP4].fields = 254299ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 254399ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 254499ecfbf8SJan Medala 254599ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_TCP6].fields = 254699ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 254799ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 254899ecfbf8SJan Medala 254999ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_UDP6].fields = 255099ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 255199ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 255299ecfbf8SJan Medala 255399ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP4].fields = 255499ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA; 255599ecfbf8SJan Medala 255699ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP6].fields = 255799ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA; 255899ecfbf8SJan Medala 255999ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP4_FRAG].fields = 256099ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA; 256199ecfbf8SJan Medala 25623adcba9aSMichal Krawczyk hash_ctrl->selected_fields[ENA_ADMIN_RSS_NOT_IP].fields = 256399ecfbf8SJan Medala ENA_ADMIN_RSS_L2_DA | ENA_ADMIN_RSS_L2_SA; 256499ecfbf8SJan Medala 256599ecfbf8SJan Medala for (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; i++) { 256699ecfbf8SJan Medala available_fields = hash_ctrl->selected_fields[i].fields & 256799ecfbf8SJan Medala hash_ctrl->supported_fields[i].fields; 256899ecfbf8SJan Medala if (available_fields != hash_ctrl->selected_fields[i].fields) { 256999ecfbf8SJan Medala ena_trc_err("hash control doesn't support all the desire configuration. proto %x supported %x selected %x\n", 257099ecfbf8SJan Medala i, hash_ctrl->supported_fields[i].fields, 257199ecfbf8SJan Medala hash_ctrl->selected_fields[i].fields); 25723adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 257399ecfbf8SJan Medala } 257499ecfbf8SJan Medala } 257599ecfbf8SJan Medala 257699ecfbf8SJan Medala rc = ena_com_set_hash_ctrl(ena_dev); 257799ecfbf8SJan Medala 257899ecfbf8SJan Medala /* In case of failure, restore the old hash ctrl */ 257999ecfbf8SJan Medala if (unlikely(rc)) 25803adcba9aSMichal Krawczyk ena_com_get_hash_ctrl(ena_dev, 0, NULL); 258199ecfbf8SJan Medala 258299ecfbf8SJan Medala return rc; 258399ecfbf8SJan Medala } 258499ecfbf8SJan Medala 258599ecfbf8SJan Medala int ena_com_fill_hash_ctrl(struct ena_com_dev *ena_dev, 258699ecfbf8SJan Medala enum ena_admin_flow_hash_proto proto, 258799ecfbf8SJan Medala u16 hash_fields) 258899ecfbf8SJan Medala { 258999ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 259099ecfbf8SJan Medala struct ena_admin_feature_rss_hash_control *hash_ctrl = rss->hash_ctrl; 259199ecfbf8SJan Medala u16 supported_fields; 259299ecfbf8SJan Medala int rc; 259399ecfbf8SJan Medala 25946dcee7cdSJan Medala if (proto >= ENA_ADMIN_RSS_PROTO_NUM) { 259599ecfbf8SJan Medala ena_trc_err("Invalid proto num (%u)\n", proto); 259699ecfbf8SJan Medala return ENA_COM_INVAL; 259799ecfbf8SJan Medala } 259899ecfbf8SJan Medala 259999ecfbf8SJan Medala /* Get the ctrl table */ 260099ecfbf8SJan Medala rc = ena_com_get_hash_ctrl(ena_dev, proto, NULL); 260199ecfbf8SJan Medala if (unlikely(rc)) 260299ecfbf8SJan Medala return rc; 260399ecfbf8SJan Medala 260499ecfbf8SJan Medala /* Make sure all the fields are supported */ 260599ecfbf8SJan Medala supported_fields = hash_ctrl->supported_fields[proto].fields; 260699ecfbf8SJan Medala if ((hash_fields & supported_fields) != hash_fields) { 260799ecfbf8SJan Medala ena_trc_err("proto %d doesn't support the required fields %x. supports only: %x\n", 260899ecfbf8SJan Medala proto, hash_fields, supported_fields); 260999ecfbf8SJan Medala } 261099ecfbf8SJan Medala 261199ecfbf8SJan Medala hash_ctrl->selected_fields[proto].fields = hash_fields; 261299ecfbf8SJan Medala 261399ecfbf8SJan Medala rc = ena_com_set_hash_ctrl(ena_dev); 261499ecfbf8SJan Medala 261599ecfbf8SJan Medala /* In case of failure, restore the old hash ctrl */ 261699ecfbf8SJan Medala if (unlikely(rc)) 26173adcba9aSMichal Krawczyk ena_com_get_hash_ctrl(ena_dev, 0, NULL); 261899ecfbf8SJan Medala 261999ecfbf8SJan Medala return 0; 262099ecfbf8SJan Medala } 262199ecfbf8SJan Medala 262299ecfbf8SJan Medala int ena_com_indirect_table_fill_entry(struct ena_com_dev *ena_dev, 262399ecfbf8SJan Medala u16 entry_idx, u16 entry_value) 262499ecfbf8SJan Medala { 262599ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 262699ecfbf8SJan Medala 262799ecfbf8SJan Medala if (unlikely(entry_idx >= (1 << rss->tbl_log_size))) 262899ecfbf8SJan Medala return ENA_COM_INVAL; 262999ecfbf8SJan Medala 263099ecfbf8SJan Medala if (unlikely((entry_value > ENA_TOTAL_NUM_QUEUES))) 263199ecfbf8SJan Medala return ENA_COM_INVAL; 263299ecfbf8SJan Medala 263399ecfbf8SJan Medala rss->host_rss_ind_tbl[entry_idx] = entry_value; 263499ecfbf8SJan Medala 263599ecfbf8SJan Medala return 0; 263699ecfbf8SJan Medala } 263799ecfbf8SJan Medala 263899ecfbf8SJan Medala int ena_com_indirect_table_set(struct ena_com_dev *ena_dev) 263999ecfbf8SJan Medala { 264099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 264199ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 264299ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 264399ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 26443adcba9aSMichal Krawczyk int ret; 264599ecfbf8SJan Medala 26463adcba9aSMichal Krawczyk if (!ena_com_check_supported_feature_id(ena_dev, 264799ecfbf8SJan Medala ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG)) { 26483adcba9aSMichal Krawczyk ena_trc_dbg("Feature %d isn't supported\n", 264999ecfbf8SJan Medala ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG); 26503adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 265199ecfbf8SJan Medala } 265299ecfbf8SJan Medala 265399ecfbf8SJan Medala ret = ena_com_ind_tbl_convert_to_device(ena_dev); 265499ecfbf8SJan Medala if (ret) { 265599ecfbf8SJan Medala ena_trc_err("Failed to convert host indirection table to device table\n"); 265699ecfbf8SJan Medala return ret; 265799ecfbf8SJan Medala } 265899ecfbf8SJan Medala 265999ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 266099ecfbf8SJan Medala 266199ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 266299ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 266399ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 266499ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG; 266599ecfbf8SJan Medala cmd.u.ind_table.size = rss->tbl_log_size; 266699ecfbf8SJan Medala cmd.u.ind_table.inline_index = 0xFFFFFFFF; 266799ecfbf8SJan Medala 266899ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 266999ecfbf8SJan Medala &cmd.control_buffer.address, 267099ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr); 267199ecfbf8SJan Medala if (unlikely(ret)) { 267299ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 267399ecfbf8SJan Medala return ret; 267499ecfbf8SJan Medala } 267599ecfbf8SJan Medala 26766dcee7cdSJan Medala cmd.control_buffer.length = (1ULL << rss->tbl_log_size) * 267799ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 267899ecfbf8SJan Medala 267999ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 268099ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 268199ecfbf8SJan Medala sizeof(cmd), 268299ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 268399ecfbf8SJan Medala sizeof(resp)); 268499ecfbf8SJan Medala 26853adcba9aSMichal Krawczyk if (unlikely(ret)) 268699ecfbf8SJan Medala ena_trc_err("Failed to set indirect table. error: %d\n", ret); 268799ecfbf8SJan Medala 26883adcba9aSMichal Krawczyk return ret; 268999ecfbf8SJan Medala } 269099ecfbf8SJan Medala 269199ecfbf8SJan Medala int ena_com_indirect_table_get(struct ena_com_dev *ena_dev, u32 *ind_tbl) 269299ecfbf8SJan Medala { 269399ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 269499ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 269599ecfbf8SJan Medala u32 tbl_size; 269699ecfbf8SJan Medala int i, rc; 269799ecfbf8SJan Medala 26986dcee7cdSJan Medala tbl_size = (1ULL << rss->tbl_log_size) * 269999ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 270099ecfbf8SJan Medala 270199ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 270299ecfbf8SJan Medala ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG, 270399ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 2704b68309beSRafal Kozik tbl_size, 0); 270599ecfbf8SJan Medala if (unlikely(rc)) 270699ecfbf8SJan Medala return rc; 270799ecfbf8SJan Medala 270899ecfbf8SJan Medala if (!ind_tbl) 270999ecfbf8SJan Medala return 0; 271099ecfbf8SJan Medala 271199ecfbf8SJan Medala for (i = 0; i < (1 << rss->tbl_log_size); i++) 271299ecfbf8SJan Medala ind_tbl[i] = rss->host_rss_ind_tbl[i]; 271399ecfbf8SJan Medala 271499ecfbf8SJan Medala return 0; 271599ecfbf8SJan Medala } 271699ecfbf8SJan Medala 271799ecfbf8SJan Medala int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 indr_tbl_log_size) 271899ecfbf8SJan Medala { 271999ecfbf8SJan Medala int rc; 272099ecfbf8SJan Medala 272199ecfbf8SJan Medala memset(&ena_dev->rss, 0x0, sizeof(ena_dev->rss)); 272299ecfbf8SJan Medala 272399ecfbf8SJan Medala rc = ena_com_indirect_table_allocate(ena_dev, indr_tbl_log_size); 272499ecfbf8SJan Medala if (unlikely(rc)) 272599ecfbf8SJan Medala goto err_indr_tbl; 272699ecfbf8SJan Medala 2727ff40db8dSMichal Krawczyk /* The following function might return unsupported in case the 2728ff40db8dSMichal Krawczyk * device doesn't support setting the key / hash function. We can safely 2729ff40db8dSMichal Krawczyk * ignore this error and have indirection table support only. 2730ff40db8dSMichal Krawczyk */ 273199ecfbf8SJan Medala rc = ena_com_hash_key_allocate(ena_dev); 2732ff40db8dSMichal Krawczyk if (likely(!rc)) 2733086c6b66SMichal Krawczyk ena_com_hash_key_fill_default_key(ena_dev); 2734ff40db8dSMichal Krawczyk else if (rc != ENA_COM_UNSUPPORTED) 2735ff40db8dSMichal Krawczyk goto err_hash_key; 2736086c6b66SMichal Krawczyk 273799ecfbf8SJan Medala rc = ena_com_hash_ctrl_init(ena_dev); 273899ecfbf8SJan Medala if (unlikely(rc)) 273999ecfbf8SJan Medala goto err_hash_ctrl; 274099ecfbf8SJan Medala 274199ecfbf8SJan Medala return 0; 274299ecfbf8SJan Medala 274399ecfbf8SJan Medala err_hash_ctrl: 274499ecfbf8SJan Medala ena_com_hash_key_destroy(ena_dev); 274599ecfbf8SJan Medala err_hash_key: 274699ecfbf8SJan Medala ena_com_indirect_table_destroy(ena_dev); 274799ecfbf8SJan Medala err_indr_tbl: 274899ecfbf8SJan Medala 274999ecfbf8SJan Medala return rc; 275099ecfbf8SJan Medala } 275199ecfbf8SJan Medala 27526dcee7cdSJan Medala void ena_com_rss_destroy(struct ena_com_dev *ena_dev) 275399ecfbf8SJan Medala { 275499ecfbf8SJan Medala ena_com_indirect_table_destroy(ena_dev); 275599ecfbf8SJan Medala ena_com_hash_key_destroy(ena_dev); 275699ecfbf8SJan Medala ena_com_hash_ctrl_destroy(ena_dev); 275799ecfbf8SJan Medala 275899ecfbf8SJan Medala memset(&ena_dev->rss, 0x0, sizeof(ena_dev->rss)); 275999ecfbf8SJan Medala } 276099ecfbf8SJan Medala 27616dcee7cdSJan Medala int ena_com_allocate_host_info(struct ena_com_dev *ena_dev) 276299ecfbf8SJan Medala { 276399ecfbf8SJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 276499ecfbf8SJan Medala 276599ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 276699ecfbf8SJan Medala SZ_4K, 276799ecfbf8SJan Medala host_attr->host_info, 276899ecfbf8SJan Medala host_attr->host_info_dma_addr, 276999ecfbf8SJan Medala host_attr->host_info_dma_handle); 277099ecfbf8SJan Medala if (unlikely(!host_attr->host_info)) 277199ecfbf8SJan Medala return ENA_COM_NO_MEM; 277299ecfbf8SJan Medala 2773b68309beSRafal Kozik host_attr->host_info->ena_spec_version = ((ENA_COMMON_SPEC_VERSION_MAJOR << 2774b68309beSRafal Kozik ENA_REGS_VERSION_MAJOR_VERSION_SHIFT) | 2775b68309beSRafal Kozik (ENA_COMMON_SPEC_VERSION_MINOR)); 2776b68309beSRafal Kozik 27776dcee7cdSJan Medala return 0; 27786dcee7cdSJan Medala } 27796dcee7cdSJan Medala 27806dcee7cdSJan Medala int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev, 27813adcba9aSMichal Krawczyk u32 debug_area_size) 27823adcba9aSMichal Krawczyk { 27836dcee7cdSJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 27846dcee7cdSJan Medala 278599ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 278699ecfbf8SJan Medala debug_area_size, 278799ecfbf8SJan Medala host_attr->debug_area_virt_addr, 278899ecfbf8SJan Medala host_attr->debug_area_dma_addr, 278999ecfbf8SJan Medala host_attr->debug_area_dma_handle); 279099ecfbf8SJan Medala if (unlikely(!host_attr->debug_area_virt_addr)) { 27916dcee7cdSJan Medala host_attr->debug_area_size = 0; 27926dcee7cdSJan Medala return ENA_COM_NO_MEM; 279399ecfbf8SJan Medala } 279499ecfbf8SJan Medala 279599ecfbf8SJan Medala host_attr->debug_area_size = debug_area_size; 279699ecfbf8SJan Medala 279799ecfbf8SJan Medala return 0; 279899ecfbf8SJan Medala } 279999ecfbf8SJan Medala 28006dcee7cdSJan Medala void ena_com_delete_host_info(struct ena_com_dev *ena_dev) 280199ecfbf8SJan Medala { 280299ecfbf8SJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 280399ecfbf8SJan Medala 280499ecfbf8SJan Medala if (host_attr->host_info) { 280599ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 280699ecfbf8SJan Medala SZ_4K, 280799ecfbf8SJan Medala host_attr->host_info, 280899ecfbf8SJan Medala host_attr->host_info_dma_addr, 280999ecfbf8SJan Medala host_attr->host_info_dma_handle); 281099ecfbf8SJan Medala host_attr->host_info = NULL; 281199ecfbf8SJan Medala } 28126dcee7cdSJan Medala } 28136dcee7cdSJan Medala 28146dcee7cdSJan Medala void ena_com_delete_debug_area(struct ena_com_dev *ena_dev) 28156dcee7cdSJan Medala { 28166dcee7cdSJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 281799ecfbf8SJan Medala 281899ecfbf8SJan Medala if (host_attr->debug_area_virt_addr) { 281999ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 282099ecfbf8SJan Medala host_attr->debug_area_size, 282199ecfbf8SJan Medala host_attr->debug_area_virt_addr, 282299ecfbf8SJan Medala host_attr->debug_area_dma_addr, 282399ecfbf8SJan Medala host_attr->debug_area_dma_handle); 282499ecfbf8SJan Medala host_attr->debug_area_virt_addr = NULL; 282599ecfbf8SJan Medala } 282699ecfbf8SJan Medala } 282799ecfbf8SJan Medala 282899ecfbf8SJan Medala int ena_com_set_host_attributes(struct ena_com_dev *ena_dev) 282999ecfbf8SJan Medala { 283099ecfbf8SJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 283199ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 283299ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 283399ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 28343adcba9aSMichal Krawczyk 2835201ff2e5SJakub Palider int ret; 283699ecfbf8SJan Medala 2837201ff2e5SJakub Palider /* Host attribute config is called before ena_com_get_dev_attr_feat 2838201ff2e5SJakub Palider * so ena_com can't check if the feature is supported. 2839201ff2e5SJakub Palider */ 284099ecfbf8SJan Medala 284199ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 284299ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 284399ecfbf8SJan Medala 284499ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 284599ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_HOST_ATTR_CONFIG; 284699ecfbf8SJan Medala 284799ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 284899ecfbf8SJan Medala &cmd.u.host_attr.debug_ba, 284999ecfbf8SJan Medala host_attr->debug_area_dma_addr); 285099ecfbf8SJan Medala if (unlikely(ret)) { 285199ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 285299ecfbf8SJan Medala return ret; 285399ecfbf8SJan Medala } 285499ecfbf8SJan Medala 285599ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 285699ecfbf8SJan Medala &cmd.u.host_attr.os_info_ba, 285799ecfbf8SJan Medala host_attr->host_info_dma_addr); 285899ecfbf8SJan Medala if (unlikely(ret)) { 285999ecfbf8SJan Medala ena_trc_err("memory address set failed\n"); 286099ecfbf8SJan Medala return ret; 286199ecfbf8SJan Medala } 286299ecfbf8SJan Medala 286399ecfbf8SJan Medala cmd.u.host_attr.debug_area_size = host_attr->debug_area_size; 286499ecfbf8SJan Medala 286599ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 286699ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 286799ecfbf8SJan Medala sizeof(cmd), 286899ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 286999ecfbf8SJan Medala sizeof(resp)); 287099ecfbf8SJan Medala 287199ecfbf8SJan Medala if (unlikely(ret)) 287299ecfbf8SJan Medala ena_trc_err("Failed to set host attributes: %d\n", ret); 287399ecfbf8SJan Medala 287499ecfbf8SJan Medala return ret; 287599ecfbf8SJan Medala } 287699ecfbf8SJan Medala 287799ecfbf8SJan Medala /* Interrupt moderation */ 287899ecfbf8SJan Medala bool ena_com_interrupt_moderation_supported(struct ena_com_dev *ena_dev) 287999ecfbf8SJan Medala { 28803adcba9aSMichal Krawczyk return ena_com_check_supported_feature_id(ena_dev, 288199ecfbf8SJan Medala ENA_ADMIN_INTERRUPT_MODERATION); 288299ecfbf8SJan Medala } 288399ecfbf8SJan Medala 2884d2138b23SMichal Krawczyk static int ena_com_update_nonadaptive_moderation_interval(u32 coalesce_usecs, 2885d2138b23SMichal Krawczyk u32 intr_delay_resolution, 2886d2138b23SMichal Krawczyk u32 *intr_moder_interval) 288799ecfbf8SJan Medala { 2888d2138b23SMichal Krawczyk if (!intr_delay_resolution) { 288999ecfbf8SJan Medala ena_trc_err("Illegal interrupt delay granularity value\n"); 289099ecfbf8SJan Medala return ENA_COM_FAULT; 289199ecfbf8SJan Medala } 289299ecfbf8SJan Medala 2893d2138b23SMichal Krawczyk *intr_moder_interval = coalesce_usecs / intr_delay_resolution; 289499ecfbf8SJan Medala 289599ecfbf8SJan Medala return 0; 289699ecfbf8SJan Medala } 289799ecfbf8SJan Medala 2898d2138b23SMichal Krawczyk 2899d2138b23SMichal Krawczyk int ena_com_update_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev, 2900d2138b23SMichal Krawczyk u32 tx_coalesce_usecs) 2901d2138b23SMichal Krawczyk { 2902d2138b23SMichal Krawczyk return ena_com_update_nonadaptive_moderation_interval(tx_coalesce_usecs, 2903d2138b23SMichal Krawczyk ena_dev->intr_delay_resolution, 2904d2138b23SMichal Krawczyk &ena_dev->intr_moder_tx_interval); 2905d2138b23SMichal Krawczyk } 2906d2138b23SMichal Krawczyk 29073adcba9aSMichal Krawczyk int ena_com_update_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev, 290899ecfbf8SJan Medala u32 rx_coalesce_usecs) 290999ecfbf8SJan Medala { 2910d2138b23SMichal Krawczyk return ena_com_update_nonadaptive_moderation_interval(rx_coalesce_usecs, 2911d2138b23SMichal Krawczyk ena_dev->intr_delay_resolution, 2912d2138b23SMichal Krawczyk &ena_dev->intr_moder_rx_interval); 291399ecfbf8SJan Medala } 291499ecfbf8SJan Medala 291599ecfbf8SJan Medala int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev) 291699ecfbf8SJan Medala { 291799ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 29186dcee7cdSJan Medala u16 delay_resolution; 291999ecfbf8SJan Medala int rc; 292099ecfbf8SJan Medala 292199ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 2922b68309beSRafal Kozik ENA_ADMIN_INTERRUPT_MODERATION, 0); 292399ecfbf8SJan Medala 292499ecfbf8SJan Medala if (rc) { 29253adcba9aSMichal Krawczyk if (rc == ENA_COM_UNSUPPORTED) { 29263adcba9aSMichal Krawczyk ena_trc_dbg("Feature %d isn't supported\n", 292799ecfbf8SJan Medala ENA_ADMIN_INTERRUPT_MODERATION); 292899ecfbf8SJan Medala rc = 0; 292999ecfbf8SJan Medala } else { 293099ecfbf8SJan Medala ena_trc_err("Failed to get interrupt moderation admin cmd. rc: %d\n", 293199ecfbf8SJan Medala rc); 293299ecfbf8SJan Medala } 293399ecfbf8SJan Medala 293499ecfbf8SJan Medala /* no moderation supported, disable adaptive support */ 293599ecfbf8SJan Medala ena_com_disable_adaptive_moderation(ena_dev); 293699ecfbf8SJan Medala return rc; 293799ecfbf8SJan Medala } 293899ecfbf8SJan Medala 293999ecfbf8SJan Medala /* if moderation is supported by device we set adaptive moderation */ 294099ecfbf8SJan Medala delay_resolution = get_resp.u.intr_moderation.intr_delay_resolution; 294199ecfbf8SJan Medala ena_com_update_intr_delay_resolution(ena_dev, delay_resolution); 2942b2b02edeSMichal Krawczyk 2943b2b02edeSMichal Krawczyk /* Disable adaptive moderation by default - can be enabled later */ 2944b2b02edeSMichal Krawczyk ena_com_disable_adaptive_moderation(ena_dev); 294599ecfbf8SJan Medala 294699ecfbf8SJan Medala return 0; 294799ecfbf8SJan Medala } 294899ecfbf8SJan Medala 29493adcba9aSMichal Krawczyk unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev) 295099ecfbf8SJan Medala { 295199ecfbf8SJan Medala return ena_dev->intr_moder_tx_interval; 295299ecfbf8SJan Medala } 295399ecfbf8SJan Medala 29543adcba9aSMichal Krawczyk unsigned int ena_com_get_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev) 295599ecfbf8SJan Medala { 2956d2138b23SMichal Krawczyk return ena_dev->intr_moder_rx_interval; 295799ecfbf8SJan Medala } 2958b68309beSRafal Kozik 2959b68309beSRafal Kozik int ena_com_config_dev_mode(struct ena_com_dev *ena_dev, 2960b68309beSRafal Kozik struct ena_admin_feature_llq_desc *llq_features, 2961b68309beSRafal Kozik struct ena_llq_configurations *llq_default_cfg) 2962b68309beSRafal Kozik { 29631e964c59SMichal Krawczyk struct ena_com_llq_info *llq_info = &ena_dev->llq_info; 2964b68309beSRafal Kozik int rc; 2965b68309beSRafal Kozik 2966b68309beSRafal Kozik if (!llq_features->max_llq_num) { 2967b68309beSRafal Kozik ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 2968b68309beSRafal Kozik return 0; 2969b68309beSRafal Kozik } 2970b68309beSRafal Kozik 2971b68309beSRafal Kozik rc = ena_com_config_llq_info(ena_dev, llq_features, llq_default_cfg); 2972b68309beSRafal Kozik if (rc) 2973b68309beSRafal Kozik return rc; 2974b68309beSRafal Kozik 2975b2b02edeSMichal Krawczyk ena_dev->tx_max_header_size = llq_info->desc_list_entry_size - 2976b2b02edeSMichal Krawczyk (llq_info->descs_num_before_header * sizeof(struct ena_eth_io_tx_desc)); 2977b68309beSRafal Kozik 297841083bd5SMichal Krawczyk if (unlikely(ena_dev->tx_max_header_size == 0)) { 2979b68309beSRafal Kozik ena_trc_err("the size of the LLQ entry is smaller than needed\n"); 2980b2b02edeSMichal Krawczyk return -EINVAL; 2981b68309beSRafal Kozik } 2982b68309beSRafal Kozik 2983b68309beSRafal Kozik ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_DEV; 2984b68309beSRafal Kozik 2985b68309beSRafal Kozik return 0; 2986b68309beSRafal Kozik } 2987