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 374b378679SShai Brandes #define ENA_MAX_BACKOFF_DELAY_EXP 16U 384b378679SShai Brandes 390c84e048SMichal Krawczyk #define ENA_MIN_ADMIN_POLL_US 100 400c84e048SMichal Krawczyk 410c84e048SMichal Krawczyk #define ENA_MAX_ADMIN_POLL_US 5000 4299ecfbf8SJan Medala 43f73f53f7SShai Brandes /* PHC definitions */ 44*319b51fdSShai Brandes #define ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC 10 45f73f53f7SShai Brandes #define ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC 1000 46*319b51fdSShai Brandes #define ENA_PHC_MAX_ERROR_BOUND 0xFFFFFFFF 47f73f53f7SShai Brandes #define ENA_PHC_REQ_ID_OFFSET 0xDEAD 48*319b51fdSShai Brandes #define ENA_PHC_ERROR_FLAGS (ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP | \ 49*319b51fdSShai Brandes ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND) 50f73f53f7SShai Brandes 5199ecfbf8SJan Medala /*****************************************************************************/ 5299ecfbf8SJan Medala /*****************************************************************************/ 5399ecfbf8SJan Medala /*****************************************************************************/ 5499ecfbf8SJan Medala 5599ecfbf8SJan Medala enum ena_cmd_status { 5699ecfbf8SJan Medala ENA_CMD_SUBMITTED, 5799ecfbf8SJan Medala ENA_CMD_COMPLETED, 5899ecfbf8SJan Medala /* Abort - canceled by the driver */ 5999ecfbf8SJan Medala ENA_CMD_ABORTED, 6099ecfbf8SJan Medala }; 6199ecfbf8SJan Medala 6299ecfbf8SJan Medala struct ena_comp_ctx { 6399ecfbf8SJan Medala ena_wait_event_t wait_event; 6499ecfbf8SJan Medala struct ena_admin_acq_entry *user_cqe; 6599ecfbf8SJan Medala u32 comp_size; 6699ecfbf8SJan Medala enum ena_cmd_status status; 6799ecfbf8SJan Medala /* status from the device */ 6899ecfbf8SJan Medala u8 comp_status; 6999ecfbf8SJan Medala u8 cmd_opcode; 7099ecfbf8SJan Medala bool occupied; 7199ecfbf8SJan Medala }; 7299ecfbf8SJan Medala 733adcba9aSMichal Krawczyk struct ena_com_stats_ctx { 743adcba9aSMichal Krawczyk struct ena_admin_aq_get_stats_cmd get_cmd; 753adcba9aSMichal Krawczyk struct ena_admin_acq_get_stats_resp get_resp; 763adcba9aSMichal Krawczyk }; 773adcba9aSMichal Krawczyk 78b2b02edeSMichal Krawczyk static int ena_com_mem_addr_set(struct ena_com_dev *ena_dev, 7999ecfbf8SJan Medala struct ena_common_mem_addr *ena_addr, 8099ecfbf8SJan Medala dma_addr_t addr) 8199ecfbf8SJan Medala { 8299ecfbf8SJan Medala if ((addr & GENMASK_ULL(ena_dev->dma_addr_bits - 1, 0)) != addr) { 83ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "DMA address has more bits than the device supports\n"); 8499ecfbf8SJan Medala return ENA_COM_INVAL; 8599ecfbf8SJan Medala } 8699ecfbf8SJan Medala 873adcba9aSMichal Krawczyk ena_addr->mem_addr_low = lower_32_bits(addr); 88a366fe41SMichal Krawczyk ena_addr->mem_addr_high = (u16)upper_32_bits(addr); 8999ecfbf8SJan Medala 9099ecfbf8SJan Medala return 0; 9199ecfbf8SJan Medala } 9299ecfbf8SJan Medala 93b4f8decdSMichal Krawczyk static int ena_com_admin_init_sq(struct ena_com_admin_queue *admin_queue) 9499ecfbf8SJan Medala { 95ac2fd8a5SMichal Krawczyk struct ena_com_dev *ena_dev = admin_queue->ena_dev; 96b4f8decdSMichal Krawczyk struct ena_com_admin_sq *sq = &admin_queue->sq; 97b4f8decdSMichal Krawczyk u16 size = ADMIN_SQ_SIZE(admin_queue->q_depth); 9899ecfbf8SJan Medala 99b4f8decdSMichal Krawczyk ENA_MEM_ALLOC_COHERENT(admin_queue->q_dmadev, size, sq->entries, sq->dma_addr, 1003adcba9aSMichal Krawczyk sq->mem_handle); 1013adcba9aSMichal Krawczyk 1023adcba9aSMichal Krawczyk if (!sq->entries) { 103ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory allocation failed\n"); 10499ecfbf8SJan Medala return ENA_COM_NO_MEM; 10599ecfbf8SJan Medala } 10699ecfbf8SJan Medala 1073adcba9aSMichal Krawczyk sq->head = 0; 1083adcba9aSMichal Krawczyk sq->tail = 0; 1093adcba9aSMichal Krawczyk sq->phase = 1; 11099ecfbf8SJan Medala 1113adcba9aSMichal Krawczyk sq->db_addr = NULL; 11299ecfbf8SJan Medala 11399ecfbf8SJan Medala return 0; 11499ecfbf8SJan Medala } 11599ecfbf8SJan Medala 116b4f8decdSMichal Krawczyk static int ena_com_admin_init_cq(struct ena_com_admin_queue *admin_queue) 11799ecfbf8SJan Medala { 118ac2fd8a5SMichal Krawczyk struct ena_com_dev *ena_dev = admin_queue->ena_dev; 119b4f8decdSMichal Krawczyk struct ena_com_admin_cq *cq = &admin_queue->cq; 120b4f8decdSMichal Krawczyk u16 size = ADMIN_CQ_SIZE(admin_queue->q_depth); 12199ecfbf8SJan Medala 122b4f8decdSMichal Krawczyk ENA_MEM_ALLOC_COHERENT(admin_queue->q_dmadev, size, cq->entries, cq->dma_addr, 1233adcba9aSMichal Krawczyk cq->mem_handle); 1243adcba9aSMichal Krawczyk 1253adcba9aSMichal Krawczyk if (!cq->entries) { 126ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory allocation failed\n"); 12799ecfbf8SJan Medala return ENA_COM_NO_MEM; 12899ecfbf8SJan Medala } 12999ecfbf8SJan Medala 1303adcba9aSMichal Krawczyk cq->head = 0; 1313adcba9aSMichal Krawczyk cq->phase = 1; 13299ecfbf8SJan Medala 13399ecfbf8SJan Medala return 0; 13499ecfbf8SJan Medala } 13599ecfbf8SJan Medala 136b4f8decdSMichal Krawczyk static int ena_com_admin_init_aenq(struct ena_com_dev *ena_dev, 13799ecfbf8SJan Medala struct ena_aenq_handlers *aenq_handlers) 13899ecfbf8SJan Medala { 139b4f8decdSMichal Krawczyk struct ena_com_aenq *aenq = &ena_dev->aenq; 14099ecfbf8SJan Medala u32 addr_low, addr_high, aenq_caps; 1413adcba9aSMichal Krawczyk u16 size; 14299ecfbf8SJan Medala 143b4f8decdSMichal Krawczyk ena_dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH; 1443adcba9aSMichal Krawczyk size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH); 145b4f8decdSMichal Krawczyk ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, size, 1463adcba9aSMichal Krawczyk aenq->entries, 1473adcba9aSMichal Krawczyk aenq->dma_addr, 1483adcba9aSMichal Krawczyk aenq->mem_handle); 14999ecfbf8SJan Medala 1503adcba9aSMichal Krawczyk if (!aenq->entries) { 151ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory allocation failed\n"); 15299ecfbf8SJan Medala return ENA_COM_NO_MEM; 15399ecfbf8SJan Medala } 15499ecfbf8SJan Medala 1553adcba9aSMichal Krawczyk aenq->head = aenq->q_depth; 1563adcba9aSMichal Krawczyk aenq->phase = 1; 15799ecfbf8SJan Medala 1583adcba9aSMichal Krawczyk addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(aenq->dma_addr); 1593adcba9aSMichal Krawczyk addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(aenq->dma_addr); 16099ecfbf8SJan Medala 161b4f8decdSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_AENQ_BASE_LO_OFF); 162b4f8decdSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_AENQ_BASE_HI_OFF); 16399ecfbf8SJan Medala 16499ecfbf8SJan Medala aenq_caps = 0; 165b4f8decdSMichal Krawczyk aenq_caps |= ena_dev->aenq.q_depth & ENA_REGS_AENQ_CAPS_AENQ_DEPTH_MASK; 16699ecfbf8SJan Medala aenq_caps |= (sizeof(struct ena_admin_aenq_entry) << 16799ecfbf8SJan Medala ENA_REGS_AENQ_CAPS_AENQ_ENTRY_SIZE_SHIFT) & 16899ecfbf8SJan Medala ENA_REGS_AENQ_CAPS_AENQ_ENTRY_SIZE_MASK; 169b4f8decdSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, aenq_caps, ena_dev->reg_bar + ENA_REGS_AENQ_CAPS_OFF); 17099ecfbf8SJan Medala 1713adcba9aSMichal Krawczyk if (unlikely(!aenq_handlers)) { 172ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "AENQ handlers pointer is NULL\n"); 1733adcba9aSMichal Krawczyk return ENA_COM_INVAL; 1743adcba9aSMichal Krawczyk } 17599ecfbf8SJan Medala 1763adcba9aSMichal Krawczyk aenq->aenq_handlers = aenq_handlers; 17799ecfbf8SJan Medala 17899ecfbf8SJan Medala return 0; 17999ecfbf8SJan Medala } 18099ecfbf8SJan Medala 181b2b02edeSMichal Krawczyk static void comp_ctxt_release(struct ena_com_admin_queue *queue, 18299ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx) 18399ecfbf8SJan Medala { 18499ecfbf8SJan Medala comp_ctx->occupied = false; 18599ecfbf8SJan Medala ATOMIC32_DEC(&queue->outstanding_cmds); 18699ecfbf8SJan Medala } 18799ecfbf8SJan Medala 188b4f8decdSMichal Krawczyk static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *admin_queue, 18999ecfbf8SJan Medala u16 command_id, bool capture) 19099ecfbf8SJan Medala { 191b4f8decdSMichal Krawczyk if (unlikely(command_id >= admin_queue->q_depth)) { 192ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 193ac2fd8a5SMichal Krawczyk "Command id is larger than the queue size. cmd_id: %u queue size %d\n", 194b4f8decdSMichal Krawczyk command_id, admin_queue->q_depth); 1956dcee7cdSJan Medala return NULL; 1966dcee7cdSJan Medala } 19799ecfbf8SJan Medala 198b4f8decdSMichal Krawczyk if (unlikely(!admin_queue->comp_ctx)) { 199ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 200ac2fd8a5SMichal Krawczyk "Completion context is NULL\n"); 201b2b02edeSMichal Krawczyk return NULL; 202b2b02edeSMichal Krawczyk } 203b2b02edeSMichal Krawczyk 204b4f8decdSMichal Krawczyk if (unlikely(admin_queue->comp_ctx[command_id].occupied && capture)) { 205ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 206ac2fd8a5SMichal Krawczyk "Completion context is occupied\n"); 2076dcee7cdSJan Medala return NULL; 2086dcee7cdSJan Medala } 20999ecfbf8SJan Medala 21099ecfbf8SJan Medala if (capture) { 211b4f8decdSMichal Krawczyk ATOMIC32_INC(&admin_queue->outstanding_cmds); 212b4f8decdSMichal Krawczyk admin_queue->comp_ctx[command_id].occupied = true; 21399ecfbf8SJan Medala } 21499ecfbf8SJan Medala 215b4f8decdSMichal Krawczyk return &admin_queue->comp_ctx[command_id]; 21699ecfbf8SJan Medala } 21799ecfbf8SJan Medala 2183adcba9aSMichal Krawczyk static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queue *admin_queue, 21999ecfbf8SJan Medala struct ena_admin_aq_entry *cmd, 22099ecfbf8SJan Medala size_t cmd_size_in_bytes, 22199ecfbf8SJan Medala struct ena_admin_acq_entry *comp, 22299ecfbf8SJan Medala size_t comp_size_in_bytes) 22399ecfbf8SJan Medala { 22499ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 22599ecfbf8SJan Medala u16 tail_masked, cmd_id; 22699ecfbf8SJan Medala u16 queue_size_mask; 22799ecfbf8SJan Medala u16 cnt; 22899ecfbf8SJan Medala 22999ecfbf8SJan Medala queue_size_mask = admin_queue->q_depth - 1; 23099ecfbf8SJan Medala 23199ecfbf8SJan Medala tail_masked = admin_queue->sq.tail & queue_size_mask; 23299ecfbf8SJan Medala 23399ecfbf8SJan Medala /* In case of queue FULL */ 234b68309beSRafal Kozik cnt = (u16)ATOMIC32_READ(&admin_queue->outstanding_cmds); 23599ecfbf8SJan Medala if (cnt >= admin_queue->q_depth) { 236ac2fd8a5SMichal Krawczyk ena_trc_dbg(admin_queue->ena_dev, "Admin queue is full.\n"); 23799ecfbf8SJan Medala admin_queue->stats.out_of_space++; 23899ecfbf8SJan Medala return ERR_PTR(ENA_COM_NO_SPACE); 23999ecfbf8SJan Medala } 24099ecfbf8SJan Medala 24199ecfbf8SJan Medala cmd_id = admin_queue->curr_cmd_id; 24299ecfbf8SJan Medala 24399ecfbf8SJan Medala cmd->aq_common_descriptor.flags |= admin_queue->sq.phase & 24499ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_PHASE_MASK; 24599ecfbf8SJan Medala 24699ecfbf8SJan Medala cmd->aq_common_descriptor.command_id |= cmd_id & 24799ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_COMMAND_ID_MASK; 24899ecfbf8SJan Medala 24999ecfbf8SJan Medala comp_ctx = get_comp_ctxt(admin_queue, cmd_id, true); 2503adcba9aSMichal Krawczyk if (unlikely(!comp_ctx)) 2513adcba9aSMichal Krawczyk return ERR_PTR(ENA_COM_INVAL); 25299ecfbf8SJan Medala 25399ecfbf8SJan Medala comp_ctx->status = ENA_CMD_SUBMITTED; 25499ecfbf8SJan Medala comp_ctx->comp_size = (u32)comp_size_in_bytes; 25599ecfbf8SJan Medala comp_ctx->user_cqe = comp; 25699ecfbf8SJan Medala comp_ctx->cmd_opcode = cmd->aq_common_descriptor.opcode; 25799ecfbf8SJan Medala 25899ecfbf8SJan Medala ENA_WAIT_EVENT_CLEAR(comp_ctx->wait_event); 25999ecfbf8SJan Medala 26099ecfbf8SJan Medala memcpy(&admin_queue->sq.entries[tail_masked], cmd, cmd_size_in_bytes); 26199ecfbf8SJan Medala 26299ecfbf8SJan Medala admin_queue->curr_cmd_id = (admin_queue->curr_cmd_id + 1) & 26399ecfbf8SJan Medala queue_size_mask; 26499ecfbf8SJan Medala 26599ecfbf8SJan Medala admin_queue->sq.tail++; 26699ecfbf8SJan Medala admin_queue->stats.submitted_cmd++; 26799ecfbf8SJan Medala 26899ecfbf8SJan Medala if (unlikely((admin_queue->sq.tail & queue_size_mask) == 0)) 26999ecfbf8SJan Medala admin_queue->sq.phase = !admin_queue->sq.phase; 27099ecfbf8SJan Medala 271b68309beSRafal Kozik ENA_DB_SYNC(&admin_queue->sq.mem_handle); 2723adcba9aSMichal Krawczyk ENA_REG_WRITE32(admin_queue->bus, admin_queue->sq.tail, 2733adcba9aSMichal Krawczyk admin_queue->sq.db_addr); 27499ecfbf8SJan Medala 27599ecfbf8SJan Medala return comp_ctx; 27699ecfbf8SJan Medala } 27799ecfbf8SJan Medala 278b4f8decdSMichal Krawczyk static int ena_com_init_comp_ctxt(struct ena_com_admin_queue *admin_queue) 27999ecfbf8SJan Medala { 280ac2fd8a5SMichal Krawczyk struct ena_com_dev *ena_dev = admin_queue->ena_dev; 281b4f8decdSMichal Krawczyk size_t size = admin_queue->q_depth * sizeof(struct ena_comp_ctx); 28299ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 28399ecfbf8SJan Medala u16 i; 28499ecfbf8SJan Medala 285b4f8decdSMichal Krawczyk admin_queue->comp_ctx = ENA_MEM_ALLOC(admin_queue->q_dmadev, size); 286b4f8decdSMichal Krawczyk if (unlikely(!admin_queue->comp_ctx)) { 287ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory allocation failed\n"); 28899ecfbf8SJan Medala return ENA_COM_NO_MEM; 28999ecfbf8SJan Medala } 29099ecfbf8SJan Medala 291b4f8decdSMichal Krawczyk for (i = 0; i < admin_queue->q_depth; i++) { 292b4f8decdSMichal Krawczyk comp_ctx = get_comp_ctxt(admin_queue, i, false); 2936dcee7cdSJan Medala if (comp_ctx) 29499ecfbf8SJan Medala ENA_WAIT_EVENT_INIT(comp_ctx->wait_event); 29599ecfbf8SJan Medala } 29699ecfbf8SJan Medala 29799ecfbf8SJan Medala return 0; 29899ecfbf8SJan Medala } 29999ecfbf8SJan Medala 3003adcba9aSMichal Krawczyk static struct ena_comp_ctx *ena_com_submit_admin_cmd(struct ena_com_admin_queue *admin_queue, 30199ecfbf8SJan Medala struct ena_admin_aq_entry *cmd, 30299ecfbf8SJan Medala size_t cmd_size_in_bytes, 30399ecfbf8SJan Medala struct ena_admin_acq_entry *comp, 30499ecfbf8SJan Medala size_t comp_size_in_bytes) 30599ecfbf8SJan Medala { 30623a70746SDaniel Mrzyglod unsigned long flags = 0; 30799ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 30899ecfbf8SJan Medala 30999ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 31099ecfbf8SJan Medala if (unlikely(!admin_queue->running_state)) { 31199ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 31299ecfbf8SJan Medala return ERR_PTR(ENA_COM_NO_DEVICE); 31399ecfbf8SJan Medala } 31499ecfbf8SJan Medala comp_ctx = __ena_com_submit_admin_cmd(admin_queue, cmd, 31599ecfbf8SJan Medala cmd_size_in_bytes, 31699ecfbf8SJan Medala comp, 31799ecfbf8SJan Medala comp_size_in_bytes); 3183adcba9aSMichal Krawczyk if (IS_ERR(comp_ctx)) 3196dcee7cdSJan Medala admin_queue->running_state = false; 32099ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 32199ecfbf8SJan Medala 32299ecfbf8SJan Medala return comp_ctx; 32399ecfbf8SJan Medala } 32499ecfbf8SJan Medala 32599ecfbf8SJan Medala static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, 3266dcee7cdSJan Medala struct ena_com_create_io_ctx *ctx, 32799ecfbf8SJan Medala struct ena_com_io_sq *io_sq) 32899ecfbf8SJan Medala { 32999ecfbf8SJan Medala size_t size; 33062e82667SFerruh Yigit int dev_node = 0; 33199ecfbf8SJan Medala 3323adcba9aSMichal Krawczyk memset(&io_sq->desc_addr, 0x0, sizeof(io_sq->desc_addr)); 33399ecfbf8SJan Medala 334b68309beSRafal Kozik io_sq->dma_addr_bits = (u8)ena_dev->dma_addr_bits; 33599ecfbf8SJan Medala io_sq->desc_entry_size = 33699ecfbf8SJan Medala (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ? 33799ecfbf8SJan Medala sizeof(struct ena_eth_io_tx_desc) : 33899ecfbf8SJan Medala sizeof(struct ena_eth_io_rx_desc); 33999ecfbf8SJan Medala 34099ecfbf8SJan Medala size = io_sq->desc_entry_size * io_sq->q_depth; 341b68309beSRafal Kozik io_sq->bus = ena_dev->bus; 34299ecfbf8SJan Medala 3433d3edc26SJan Medala if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) { 3443d3edc26SJan Medala ENA_MEM_ALLOC_COHERENT_NODE(ena_dev->dmadev, 3453d3edc26SJan Medala size, 3463d3edc26SJan Medala io_sq->desc_addr.virt_addr, 3473d3edc26SJan Medala io_sq->desc_addr.phys_addr, 3483adcba9aSMichal Krawczyk io_sq->desc_addr.mem_handle, 3493d3edc26SJan Medala ctx->numa_node, 3503d3edc26SJan Medala dev_node); 3513adcba9aSMichal Krawczyk if (!io_sq->desc_addr.virt_addr) { 35299ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 35399ecfbf8SJan Medala size, 35499ecfbf8SJan Medala io_sq->desc_addr.virt_addr, 35599ecfbf8SJan Medala io_sq->desc_addr.phys_addr, 35699ecfbf8SJan Medala io_sq->desc_addr.mem_handle); 3573adcba9aSMichal Krawczyk } 35899ecfbf8SJan Medala 35999ecfbf8SJan Medala if (!io_sq->desc_addr.virt_addr) { 360ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory allocation failed\n"); 36199ecfbf8SJan Medala return ENA_COM_NO_MEM; 36299ecfbf8SJan Medala } 363b68309beSRafal Kozik } 364b68309beSRafal Kozik 365b68309beSRafal Kozik if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 366b68309beSRafal Kozik /* Allocate bounce buffers */ 367b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.buffer_size = 368b2b02edeSMichal Krawczyk ena_dev->llq_info.desc_list_entry_size; 369b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.buffers_num = 370b2b02edeSMichal Krawczyk ENA_COM_BOUNCE_BUFFER_CNTRL_CNT; 371b68309beSRafal Kozik io_sq->bounce_buf_ctrl.next_to_use = 0; 372b68309beSRafal Kozik 373f73f53f7SShai Brandes size = (size_t)io_sq->bounce_buf_ctrl.buffer_size * 374b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.buffers_num; 375b68309beSRafal Kozik 376b68309beSRafal Kozik ENA_MEM_ALLOC_NODE(ena_dev->dmadev, 377b68309beSRafal Kozik size, 378b68309beSRafal Kozik io_sq->bounce_buf_ctrl.base_buffer, 379b68309beSRafal Kozik ctx->numa_node, 380b68309beSRafal Kozik dev_node); 381b68309beSRafal Kozik if (!io_sq->bounce_buf_ctrl.base_buffer) 382b68309beSRafal Kozik io_sq->bounce_buf_ctrl.base_buffer = ENA_MEM_ALLOC(ena_dev->dmadev, size); 383b68309beSRafal Kozik 384b68309beSRafal Kozik if (!io_sq->bounce_buf_ctrl.base_buffer) { 385ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Bounce buffer memory allocation failed\n"); 386b68309beSRafal Kozik return ENA_COM_NO_MEM; 387b68309beSRafal Kozik } 388b68309beSRafal Kozik 389b2b02edeSMichal Krawczyk memcpy(&io_sq->llq_info, &ena_dev->llq_info, 390b2b02edeSMichal Krawczyk sizeof(io_sq->llq_info)); 391b68309beSRafal Kozik 392b68309beSRafal Kozik /* Initiate the first bounce buffer */ 393b68309beSRafal Kozik io_sq->llq_buf_ctrl.curr_bounce_buf = 394b68309beSRafal Kozik ena_com_get_next_bounce_buffer(&io_sq->bounce_buf_ctrl); 395b68309beSRafal Kozik memset(io_sq->llq_buf_ctrl.curr_bounce_buf, 396b68309beSRafal Kozik 0x0, io_sq->llq_info.desc_list_entry_size); 397b68309beSRafal Kozik io_sq->llq_buf_ctrl.descs_left_in_line = 398b68309beSRafal Kozik io_sq->llq_info.descs_num_before_header; 399f1453604SMichal Krawczyk io_sq->disable_meta_caching = 400f1453604SMichal Krawczyk io_sq->llq_info.disable_meta_caching; 401b68309beSRafal Kozik 402b68309beSRafal Kozik if (io_sq->llq_info.max_entries_in_tx_burst > 0) 403b68309beSRafal Kozik io_sq->entries_in_tx_burst_left = 404b68309beSRafal Kozik io_sq->llq_info.max_entries_in_tx_burst; 405b68309beSRafal Kozik } 40699ecfbf8SJan Medala 40799ecfbf8SJan Medala io_sq->tail = 0; 40899ecfbf8SJan Medala io_sq->next_to_comp = 0; 40999ecfbf8SJan Medala io_sq->phase = 1; 41099ecfbf8SJan Medala 41199ecfbf8SJan Medala return 0; 41299ecfbf8SJan Medala } 41399ecfbf8SJan Medala 41499ecfbf8SJan Medala static int ena_com_init_io_cq(struct ena_com_dev *ena_dev, 4156dcee7cdSJan Medala struct ena_com_create_io_ctx *ctx, 41699ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 41799ecfbf8SJan Medala { 41899ecfbf8SJan Medala size_t size; 41962e82667SFerruh Yigit int prev_node = 0; 42099ecfbf8SJan Medala 4213adcba9aSMichal Krawczyk memset(&io_cq->cdesc_addr, 0x0, sizeof(io_cq->cdesc_addr)); 42299ecfbf8SJan Medala 42399ecfbf8SJan Medala /* Use the basic completion descriptor for Rx */ 42499ecfbf8SJan Medala io_cq->cdesc_entry_size_in_bytes = 42599ecfbf8SJan Medala (io_cq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ? 42699ecfbf8SJan Medala sizeof(struct ena_eth_io_tx_cdesc) : 42799ecfbf8SJan Medala sizeof(struct ena_eth_io_rx_cdesc_base); 42899ecfbf8SJan Medala 42999ecfbf8SJan Medala size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth; 430b68309beSRafal Kozik io_cq->bus = ena_dev->bus; 43199ecfbf8SJan Medala 4324be6bc7fSMichal Krawczyk ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(ena_dev->dmadev, 4333d3edc26SJan Medala size, 4343d3edc26SJan Medala io_cq->cdesc_addr.virt_addr, 4353d3edc26SJan Medala io_cq->cdesc_addr.phys_addr, 4363adcba9aSMichal Krawczyk io_cq->cdesc_addr.mem_handle, 4373d3edc26SJan Medala ctx->numa_node, 4384be6bc7fSMichal Krawczyk prev_node, 4394be6bc7fSMichal Krawczyk ENA_CDESC_RING_SIZE_ALIGNMENT); 4403adcba9aSMichal Krawczyk if (!io_cq->cdesc_addr.virt_addr) { 4414be6bc7fSMichal Krawczyk ENA_MEM_ALLOC_COHERENT_ALIGNED(ena_dev->dmadev, 44299ecfbf8SJan Medala size, 44399ecfbf8SJan Medala io_cq->cdesc_addr.virt_addr, 44499ecfbf8SJan Medala io_cq->cdesc_addr.phys_addr, 4454be6bc7fSMichal Krawczyk io_cq->cdesc_addr.mem_handle, 4464be6bc7fSMichal Krawczyk ENA_CDESC_RING_SIZE_ALIGNMENT); 4473adcba9aSMichal Krawczyk } 44899ecfbf8SJan Medala 44999ecfbf8SJan Medala if (!io_cq->cdesc_addr.virt_addr) { 450ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory allocation failed\n"); 45199ecfbf8SJan Medala return ENA_COM_NO_MEM; 45299ecfbf8SJan Medala } 45399ecfbf8SJan Medala 45499ecfbf8SJan Medala io_cq->phase = 1; 45599ecfbf8SJan Medala io_cq->head = 0; 45699ecfbf8SJan Medala 45799ecfbf8SJan Medala return 0; 45899ecfbf8SJan Medala } 45999ecfbf8SJan Medala 4603adcba9aSMichal Krawczyk static void ena_com_handle_single_admin_completion(struct ena_com_admin_queue *admin_queue, 46199ecfbf8SJan Medala struct ena_admin_acq_entry *cqe) 46299ecfbf8SJan Medala { 46399ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 46499ecfbf8SJan Medala u16 cmd_id; 46599ecfbf8SJan Medala 46699ecfbf8SJan Medala cmd_id = cqe->acq_common_descriptor.command & 46799ecfbf8SJan Medala ENA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID_MASK; 46899ecfbf8SJan Medala 46999ecfbf8SJan Medala comp_ctx = get_comp_ctxt(admin_queue, cmd_id, false); 4706dcee7cdSJan Medala if (unlikely(!comp_ctx)) { 471ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 472ac2fd8a5SMichal Krawczyk "comp_ctx is NULL. Changing the admin queue running state\n"); 4736dcee7cdSJan Medala admin_queue->running_state = false; 4746dcee7cdSJan Medala return; 4756dcee7cdSJan Medala } 47699ecfbf8SJan Medala 47799ecfbf8SJan Medala comp_ctx->status = ENA_CMD_COMPLETED; 47899ecfbf8SJan Medala comp_ctx->comp_status = cqe->acq_common_descriptor.status; 47999ecfbf8SJan Medala 48099ecfbf8SJan Medala if (comp_ctx->user_cqe) 48199ecfbf8SJan Medala memcpy(comp_ctx->user_cqe, (void *)cqe, comp_ctx->comp_size); 48299ecfbf8SJan Medala 48399ecfbf8SJan Medala if (!admin_queue->polling) 48499ecfbf8SJan Medala ENA_WAIT_EVENT_SIGNAL(comp_ctx->wait_event); 48599ecfbf8SJan Medala } 48699ecfbf8SJan Medala 4873adcba9aSMichal Krawczyk static void ena_com_handle_admin_completion(struct ena_com_admin_queue *admin_queue) 48899ecfbf8SJan Medala { 48999ecfbf8SJan Medala struct ena_admin_acq_entry *cqe = NULL; 49099ecfbf8SJan Medala u16 comp_num = 0; 49199ecfbf8SJan Medala u16 head_masked; 49299ecfbf8SJan Medala u8 phase; 49399ecfbf8SJan Medala 49499ecfbf8SJan Medala head_masked = admin_queue->cq.head & (admin_queue->q_depth - 1); 49599ecfbf8SJan Medala phase = admin_queue->cq.phase; 49699ecfbf8SJan Medala 49799ecfbf8SJan Medala cqe = &admin_queue->cq.entries[head_masked]; 49899ecfbf8SJan Medala 49999ecfbf8SJan Medala /* Go over all the completions */ 500b68309beSRafal Kozik while ((READ_ONCE8(cqe->acq_common_descriptor.flags) & 50199ecfbf8SJan Medala ENA_ADMIN_ACQ_COMMON_DESC_PHASE_MASK) == phase) { 50299ecfbf8SJan Medala /* Do not read the rest of the completion entry before the 50399ecfbf8SJan Medala * phase bit was validated 50499ecfbf8SJan Medala */ 505b68309beSRafal Kozik dma_rmb(); 50699ecfbf8SJan Medala ena_com_handle_single_admin_completion(admin_queue, cqe); 50799ecfbf8SJan Medala 50899ecfbf8SJan Medala head_masked++; 50999ecfbf8SJan Medala comp_num++; 51099ecfbf8SJan Medala if (unlikely(head_masked == admin_queue->q_depth)) { 51199ecfbf8SJan Medala head_masked = 0; 51299ecfbf8SJan Medala phase = !phase; 51399ecfbf8SJan Medala } 51499ecfbf8SJan Medala 51599ecfbf8SJan Medala cqe = &admin_queue->cq.entries[head_masked]; 51699ecfbf8SJan Medala } 51799ecfbf8SJan Medala 51899ecfbf8SJan Medala admin_queue->cq.head += comp_num; 51999ecfbf8SJan Medala admin_queue->cq.phase = phase; 52099ecfbf8SJan Medala admin_queue->sq.head += comp_num; 52199ecfbf8SJan Medala admin_queue->stats.completed_cmd += comp_num; 52299ecfbf8SJan Medala } 52399ecfbf8SJan Medala 524ac2fd8a5SMichal Krawczyk static int ena_com_comp_status_to_errno(struct ena_com_admin_queue *admin_queue, 525ac2fd8a5SMichal Krawczyk u8 comp_status) 52699ecfbf8SJan Medala { 52799ecfbf8SJan Medala if (unlikely(comp_status != 0)) 528ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 529ac2fd8a5SMichal Krawczyk "Admin command failed[%u]\n", comp_status); 53099ecfbf8SJan Medala 53199ecfbf8SJan Medala switch (comp_status) { 53299ecfbf8SJan Medala case ENA_ADMIN_SUCCESS: 533b2b02edeSMichal Krawczyk return ENA_COM_OK; 53499ecfbf8SJan Medala case ENA_ADMIN_RESOURCE_ALLOCATION_FAILURE: 53599ecfbf8SJan Medala return ENA_COM_NO_MEM; 53699ecfbf8SJan Medala case ENA_ADMIN_UNSUPPORTED_OPCODE: 5373adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 53899ecfbf8SJan Medala case ENA_ADMIN_BAD_OPCODE: 53999ecfbf8SJan Medala case ENA_ADMIN_MALFORMED_REQUEST: 54099ecfbf8SJan Medala case ENA_ADMIN_ILLEGAL_PARAMETER: 54199ecfbf8SJan Medala case ENA_ADMIN_UNKNOWN_ERROR: 54299ecfbf8SJan Medala return ENA_COM_INVAL; 5438eaf9fedSMichal Krawczyk case ENA_ADMIN_RESOURCE_BUSY: 5448eaf9fedSMichal Krawczyk return ENA_COM_TRY_AGAIN; 54599ecfbf8SJan Medala } 54699ecfbf8SJan Medala 547b2b02edeSMichal Krawczyk return ENA_COM_INVAL; 54899ecfbf8SJan Medala } 54999ecfbf8SJan Medala 5500c84e048SMichal Krawczyk static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us) 5510c84e048SMichal Krawczyk { 5524b378679SShai Brandes exp = ENA_MIN32(ENA_MAX_BACKOFF_DELAY_EXP, exp); 5530c84e048SMichal Krawczyk delay_us = ENA_MAX32(ENA_MIN_ADMIN_POLL_US, delay_us); 5544b378679SShai Brandes delay_us = ENA_MIN32(ENA_MAX_ADMIN_POLL_US, delay_us * (1U << exp)); 5550c84e048SMichal Krawczyk ENA_USLEEP(delay_us); 5560c84e048SMichal Krawczyk } 5570c84e048SMichal Krawczyk 5583adcba9aSMichal Krawczyk static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx, 55999ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue) 56099ecfbf8SJan Medala { 5615fe8c8a2SFerruh Yigit unsigned long flags = 0; 562b2b02edeSMichal Krawczyk ena_time_t timeout; 56399ecfbf8SJan Medala int ret; 5640c84e048SMichal Krawczyk u32 exp = 0; 56599ecfbf8SJan Medala 5663adcba9aSMichal Krawczyk timeout = ENA_GET_SYSTEM_TIMEOUT(admin_queue->completion_timeout); 56799ecfbf8SJan Medala 5683adcba9aSMichal Krawczyk while (1) { 5693adcba9aSMichal Krawczyk ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 5703adcba9aSMichal Krawczyk ena_com_handle_admin_completion(admin_queue); 5713adcba9aSMichal Krawczyk ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 5723adcba9aSMichal Krawczyk 5733adcba9aSMichal Krawczyk if (comp_ctx->status != ENA_CMD_SUBMITTED) 5743adcba9aSMichal Krawczyk break; 5753adcba9aSMichal Krawczyk 5763adcba9aSMichal Krawczyk if (ENA_TIME_EXPIRE(timeout)) { 577ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 578ac2fd8a5SMichal Krawczyk "Wait for completion (polling) timeout\n"); 57999ecfbf8SJan Medala /* ENA didn't have any completion */ 58099ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 58199ecfbf8SJan Medala admin_queue->stats.no_completion++; 58299ecfbf8SJan Medala admin_queue->running_state = false; 58399ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 58499ecfbf8SJan Medala 58599ecfbf8SJan Medala ret = ENA_COM_TIMER_EXPIRED; 58699ecfbf8SJan Medala goto err; 58799ecfbf8SJan Medala } 58899ecfbf8SJan Medala 5890c84e048SMichal Krawczyk ena_delay_exponential_backoff_us(exp++, 5900c84e048SMichal Krawczyk admin_queue->ena_dev->ena_min_poll_delay_us); 59199ecfbf8SJan Medala } 59299ecfbf8SJan Medala 59399ecfbf8SJan Medala if (unlikely(comp_ctx->status == ENA_CMD_ABORTED)) { 594ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, "Command was aborted\n"); 59599ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 59699ecfbf8SJan Medala admin_queue->stats.aborted_cmd++; 59799ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 59899ecfbf8SJan Medala ret = ENA_COM_NO_DEVICE; 59999ecfbf8SJan Medala goto err; 60099ecfbf8SJan Medala } 60199ecfbf8SJan Medala 6023adcba9aSMichal Krawczyk ENA_WARN(comp_ctx->status != ENA_CMD_COMPLETED, 603ac2fd8a5SMichal Krawczyk admin_queue->ena_dev, "Invalid comp status %d\n", 604ac2fd8a5SMichal Krawczyk comp_ctx->status); 60599ecfbf8SJan Medala 606ac2fd8a5SMichal Krawczyk ret = ena_com_comp_status_to_errno(admin_queue, comp_ctx->comp_status); 60799ecfbf8SJan Medala err: 60899ecfbf8SJan Medala comp_ctxt_release(admin_queue, comp_ctx); 60999ecfbf8SJan Medala return ret; 61099ecfbf8SJan Medala } 61199ecfbf8SJan Medala 612b19f366cSMichal Krawczyk /* 613b68309beSRafal Kozik * Set the LLQ configurations of the firmware 614b68309beSRafal Kozik * 615b2b02edeSMichal Krawczyk * The driver provides only the enabled feature values to the device, 616b68309beSRafal Kozik * which in turn, checks if they are supported. 617b68309beSRafal Kozik */ 618b68309beSRafal Kozik static int ena_com_set_llq(struct ena_com_dev *ena_dev) 619b68309beSRafal Kozik { 620b68309beSRafal Kozik struct ena_com_admin_queue *admin_queue; 621b68309beSRafal Kozik struct ena_admin_set_feat_cmd cmd; 622b68309beSRafal Kozik struct ena_admin_set_feat_resp resp; 623b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &ena_dev->llq_info; 624b68309beSRafal Kozik int ret; 625b68309beSRafal Kozik 626b68309beSRafal Kozik memset(&cmd, 0x0, sizeof(cmd)); 627b68309beSRafal Kozik admin_queue = &ena_dev->admin_queue; 628b68309beSRafal Kozik 629b68309beSRafal Kozik cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 630b68309beSRafal Kozik cmd.feat_common.feature_id = ENA_ADMIN_LLQ; 631b68309beSRafal Kozik 632b68309beSRafal Kozik cmd.u.llq.header_location_ctrl_enabled = llq_info->header_location_ctrl; 633b68309beSRafal Kozik cmd.u.llq.entry_size_ctrl_enabled = llq_info->desc_list_entry_size_ctrl; 634b68309beSRafal Kozik cmd.u.llq.desc_num_before_header_enabled = llq_info->descs_num_before_header; 635b68309beSRafal Kozik cmd.u.llq.descriptors_stride_ctrl_enabled = llq_info->desc_stride_ctrl; 636b68309beSRafal Kozik 6377df844b7SMichal Krawczyk cmd.u.llq.accel_mode.u.set.enabled_flags = 6387df844b7SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING) | 639f1453604SMichal Krawczyk BIT(ENA_ADMIN_LIMIT_TX_BURST); 640f1453604SMichal Krawczyk 641b68309beSRafal Kozik ret = ena_com_execute_admin_command(admin_queue, 642b68309beSRafal Kozik (struct ena_admin_aq_entry *)&cmd, 643b68309beSRafal Kozik sizeof(cmd), 644b68309beSRafal Kozik (struct ena_admin_acq_entry *)&resp, 645b68309beSRafal Kozik sizeof(resp)); 646b68309beSRafal Kozik 647b68309beSRafal Kozik if (unlikely(ret)) 648ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to set LLQ configurations: %d\n", ret); 649b68309beSRafal Kozik 650b68309beSRafal Kozik return ret; 651b68309beSRafal Kozik } 652b68309beSRafal Kozik 653b68309beSRafal Kozik static int ena_com_config_llq_info(struct ena_com_dev *ena_dev, 654b68309beSRafal Kozik struct ena_admin_feature_llq_desc *llq_features, 655b68309beSRafal Kozik struct ena_llq_configurations *llq_default_cfg) 656b68309beSRafal Kozik { 657b68309beSRafal Kozik struct ena_com_llq_info *llq_info = &ena_dev->llq_info; 6587df844b7SMichal Krawczyk struct ena_admin_accel_mode_get llq_accel_mode_get; 659b68309beSRafal Kozik u16 supported_feat; 660b68309beSRafal Kozik int rc; 661b68309beSRafal Kozik 662b68309beSRafal Kozik memset(llq_info, 0, sizeof(*llq_info)); 663b68309beSRafal Kozik 664b68309beSRafal Kozik supported_feat = llq_features->header_location_ctrl_supported; 665b68309beSRafal Kozik 666b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_header_location)) { 667b2b02edeSMichal Krawczyk llq_info->header_location_ctrl = 668b2b02edeSMichal Krawczyk llq_default_cfg->llq_header_location; 669b68309beSRafal Kozik } else { 670ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid header location control, supported: 0x%x\n", 671b68309beSRafal Kozik supported_feat); 672f73f53f7SShai Brandes return ENA_COM_INVAL; 673b68309beSRafal Kozik } 674b68309beSRafal Kozik 675b68309beSRafal Kozik if (likely(llq_info->header_location_ctrl == ENA_ADMIN_INLINE_HEADER)) { 676b68309beSRafal Kozik supported_feat = llq_features->descriptors_stride_ctrl_supported; 677b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_stride_ctrl)) { 678b68309beSRafal Kozik llq_info->desc_stride_ctrl = llq_default_cfg->llq_stride_ctrl; 679b68309beSRafal Kozik } else { 680b68309beSRafal Kozik if (supported_feat & ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY) { 681b68309beSRafal Kozik llq_info->desc_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY; 682b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_SINGLE_DESC_PER_ENTRY) { 683b68309beSRafal Kozik llq_info->desc_stride_ctrl = ENA_ADMIN_SINGLE_DESC_PER_ENTRY; 684b68309beSRafal Kozik } else { 685ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid desc_stride_ctrl, supported: 0x%x\n", 686b68309beSRafal Kozik supported_feat); 687f73f53f7SShai Brandes return ENA_COM_INVAL; 688b68309beSRafal Kozik } 689b68309beSRafal Kozik 690ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Default llq stride ctrl is not supported, performing fallback, default: 0x%x, supported: 0x%x, used: 0x%x\n", 691b68309beSRafal Kozik llq_default_cfg->llq_stride_ctrl, 692b68309beSRafal Kozik supported_feat, 693b68309beSRafal Kozik llq_info->desc_stride_ctrl); 694b68309beSRafal Kozik } 695b68309beSRafal Kozik } else { 696b68309beSRafal Kozik llq_info->desc_stride_ctrl = 0; 697b68309beSRafal Kozik } 698b68309beSRafal Kozik 699b68309beSRafal Kozik supported_feat = llq_features->entry_size_ctrl_supported; 700b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_ring_entry_size)) { 701b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = llq_default_cfg->llq_ring_entry_size; 702b68309beSRafal Kozik llq_info->desc_list_entry_size = llq_default_cfg->llq_ring_entry_size_value; 703b68309beSRafal Kozik } else { 704b68309beSRafal Kozik if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_128B) { 705b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_128B; 706b68309beSRafal Kozik llq_info->desc_list_entry_size = 128; 707b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_192B) { 708b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_192B; 709b68309beSRafal Kozik llq_info->desc_list_entry_size = 192; 710b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LIST_ENTRY_SIZE_256B) { 711b68309beSRafal Kozik llq_info->desc_list_entry_size_ctrl = ENA_ADMIN_LIST_ENTRY_SIZE_256B; 712b68309beSRafal Kozik llq_info->desc_list_entry_size = 256; 713b68309beSRafal Kozik } else { 714ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid entry_size_ctrl, supported: 0x%x\n", 715ac2fd8a5SMichal Krawczyk supported_feat); 716f73f53f7SShai Brandes return ENA_COM_INVAL; 717b68309beSRafal Kozik } 718b68309beSRafal Kozik 719ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Default llq ring entry size is not supported, performing fallback, default: 0x%x, supported: 0x%x, used: 0x%x\n", 720b68309beSRafal Kozik llq_default_cfg->llq_ring_entry_size, 721b68309beSRafal Kozik supported_feat, 722b68309beSRafal Kozik llq_info->desc_list_entry_size); 723b68309beSRafal Kozik } 724b68309beSRafal Kozik if (unlikely(llq_info->desc_list_entry_size & 0x7)) { 725b68309beSRafal Kozik /* The desc list entry size should be whole multiply of 8 726b68309beSRafal Kozik * This requirement comes from __iowrite64_copy() 727b68309beSRafal Kozik */ 728ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Illegal entry size %d\n", 729b68309beSRafal Kozik llq_info->desc_list_entry_size); 730f73f53f7SShai Brandes return ENA_COM_INVAL; 731b68309beSRafal Kozik } 732b68309beSRafal Kozik 733b68309beSRafal Kozik if (llq_info->desc_stride_ctrl == ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY) 734b68309beSRafal Kozik llq_info->descs_per_entry = llq_info->desc_list_entry_size / 735b68309beSRafal Kozik sizeof(struct ena_eth_io_tx_desc); 736b68309beSRafal Kozik else 737b68309beSRafal Kozik llq_info->descs_per_entry = 1; 738b68309beSRafal Kozik 739b68309beSRafal Kozik supported_feat = llq_features->desc_num_before_header_supported; 740b68309beSRafal Kozik if (likely(supported_feat & llq_default_cfg->llq_num_decs_before_header)) { 741b68309beSRafal Kozik llq_info->descs_num_before_header = llq_default_cfg->llq_num_decs_before_header; 742b68309beSRafal Kozik } else { 743b68309beSRafal Kozik if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2) { 744b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2; 745b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_1) { 746b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_1; 747b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_4) { 748b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_4; 749b68309beSRafal Kozik } else if (supported_feat & ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_8) { 750b68309beSRafal Kozik llq_info->descs_num_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_8; 751b68309beSRafal Kozik } else { 752ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid descs_num_before_header, supported: 0x%x\n", 753b68309beSRafal Kozik supported_feat); 754f73f53f7SShai Brandes return ENA_COM_INVAL; 755b68309beSRafal Kozik } 756b68309beSRafal Kozik 757ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Default llq num descs before header is not supported, performing fallback, default: 0x%x, supported: 0x%x, used: 0x%x\n", 758b68309beSRafal Kozik llq_default_cfg->llq_num_decs_before_header, 759b68309beSRafal Kozik supported_feat, 760b68309beSRafal Kozik llq_info->descs_num_before_header); 761b68309beSRafal Kozik } 762f1453604SMichal Krawczyk /* Check for accelerated queue supported */ 7637df844b7SMichal Krawczyk llq_accel_mode_get = llq_features->accel_mode.u.get; 764b68309beSRafal Kozik 7657df844b7SMichal Krawczyk llq_info->disable_meta_caching = 7667df844b7SMichal Krawczyk !!(llq_accel_mode_get.supported_flags & 7677df844b7SMichal Krawczyk BIT(ENA_ADMIN_DISABLE_META_CACHING)); 7687df844b7SMichal Krawczyk 7697df844b7SMichal Krawczyk if (llq_accel_mode_get.supported_flags & BIT(ENA_ADMIN_LIMIT_TX_BURST)) 770b68309beSRafal Kozik llq_info->max_entries_in_tx_burst = 7717df844b7SMichal Krawczyk llq_accel_mode_get.max_tx_burst_size / 772f1453604SMichal Krawczyk llq_default_cfg->llq_ring_entry_size_value; 773b68309beSRafal Kozik 774b68309beSRafal Kozik rc = ena_com_set_llq(ena_dev); 775b68309beSRafal Kozik if (rc) 776ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Cannot set LLQ configuration: %d\n", rc); 777b68309beSRafal Kozik 778b2b02edeSMichal Krawczyk return rc; 779b68309beSRafal Kozik } 780b68309beSRafal Kozik 7813adcba9aSMichal Krawczyk static int ena_com_wait_and_process_admin_cq_interrupts(struct ena_comp_ctx *comp_ctx, 78299ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue) 78399ecfbf8SJan Medala { 78423a70746SDaniel Mrzyglod unsigned long flags = 0; 7853adcba9aSMichal Krawczyk int ret; 78699ecfbf8SJan Medala 78799ecfbf8SJan Medala ENA_WAIT_EVENT_WAIT(comp_ctx->wait_event, 7883adcba9aSMichal Krawczyk admin_queue->completion_timeout); 78999ecfbf8SJan Medala 79099ecfbf8SJan Medala /* In case the command wasn't completed find out the root cause. 79199ecfbf8SJan Medala * There might be 2 kinds of errors 79299ecfbf8SJan Medala * 1) No completion (timeout reached) 79399ecfbf8SJan Medala * 2) There is completion but the device didn't get any msi-x interrupt. 79499ecfbf8SJan Medala */ 79599ecfbf8SJan Medala if (unlikely(comp_ctx->status == ENA_CMD_SUBMITTED)) { 79699ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 79799ecfbf8SJan Medala ena_com_handle_admin_completion(admin_queue); 79899ecfbf8SJan Medala admin_queue->stats.no_completion++; 79999ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 80099ecfbf8SJan Medala 801b2b02edeSMichal Krawczyk if (comp_ctx->status == ENA_CMD_COMPLETED) { 802ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 803ac2fd8a5SMichal Krawczyk "The ena device sent a completion but the driver didn't receive a MSI-X interrupt (cmd %d), autopolling mode is %s\n", 804b2b02edeSMichal Krawczyk comp_ctx->cmd_opcode, admin_queue->auto_polling ? "ON" : "OFF"); 805b2b02edeSMichal Krawczyk /* Check if fallback to polling is enabled */ 806b2b02edeSMichal Krawczyk if (admin_queue->auto_polling) 807b2b02edeSMichal Krawczyk admin_queue->polling = true; 808b2b02edeSMichal Krawczyk } else { 809ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 810ac2fd8a5SMichal Krawczyk "The ena device didn't send a completion for the admin cmd %d status %d\n", 81199ecfbf8SJan Medala comp_ctx->cmd_opcode, comp_ctx->status); 812b2b02edeSMichal Krawczyk } 813b2b02edeSMichal Krawczyk /* Check if shifted to polling mode. 814b2b02edeSMichal Krawczyk * This will happen if there is a completion without an interrupt 815b2b02edeSMichal Krawczyk * and autopolling mode is enabled. Continuing normal execution in such case 816b2b02edeSMichal Krawczyk */ 817b2b02edeSMichal Krawczyk if (!admin_queue->polling) { 81899ecfbf8SJan Medala admin_queue->running_state = false; 81999ecfbf8SJan Medala ret = ENA_COM_TIMER_EXPIRED; 82099ecfbf8SJan Medala goto err; 82199ecfbf8SJan Medala } 822b2b02edeSMichal Krawczyk } 82399ecfbf8SJan Medala 824ac2fd8a5SMichal Krawczyk ret = ena_com_comp_status_to_errno(admin_queue, comp_ctx->comp_status); 82599ecfbf8SJan Medala err: 82699ecfbf8SJan Medala comp_ctxt_release(admin_queue, comp_ctx); 82799ecfbf8SJan Medala return ret; 82899ecfbf8SJan Medala } 82999ecfbf8SJan Medala 83099ecfbf8SJan Medala /* This method read the hardware device register through posting writes 83199ecfbf8SJan Medala * and waiting for response 83299ecfbf8SJan Medala * On timeout the function will return ENA_MMIO_READ_TIMEOUT 83399ecfbf8SJan Medala */ 83499ecfbf8SJan Medala static u32 ena_com_reg_bar_read32(struct ena_com_dev *ena_dev, u16 offset) 83599ecfbf8SJan Medala { 83699ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 83799ecfbf8SJan Medala volatile struct ena_admin_ena_mmio_req_read_less_resp *read_resp = 83899ecfbf8SJan Medala mmio_read->read_resp; 8393adcba9aSMichal Krawczyk u32 mmio_read_reg, ret, i; 84023a70746SDaniel Mrzyglod unsigned long flags = 0; 8413adcba9aSMichal Krawczyk u32 timeout = mmio_read->reg_read_to; 84299ecfbf8SJan Medala 84399ecfbf8SJan Medala ENA_MIGHT_SLEEP(); 84499ecfbf8SJan Medala 8453adcba9aSMichal Krawczyk if (timeout == 0) 8463adcba9aSMichal Krawczyk timeout = ENA_REG_READ_TIMEOUT; 8473adcba9aSMichal Krawczyk 84899ecfbf8SJan Medala /* If readless is disabled, perform regular read */ 84999ecfbf8SJan Medala if (!mmio_read->readless_supported) 8503adcba9aSMichal Krawczyk return ENA_REG_READ32(ena_dev->bus, ena_dev->reg_bar + offset); 85199ecfbf8SJan Medala 85299ecfbf8SJan Medala ENA_SPINLOCK_LOCK(mmio_read->lock, flags); 85399ecfbf8SJan Medala mmio_read->seq_num++; 85499ecfbf8SJan Medala 85599ecfbf8SJan Medala read_resp->req_id = mmio_read->seq_num + 0xDEAD; 85699ecfbf8SJan Medala mmio_read_reg = (offset << ENA_REGS_MMIO_REG_READ_REG_OFF_SHIFT) & 85799ecfbf8SJan Medala ENA_REGS_MMIO_REG_READ_REG_OFF_MASK; 85899ecfbf8SJan Medala mmio_read_reg |= mmio_read->seq_num & 85999ecfbf8SJan Medala ENA_REGS_MMIO_REG_READ_REQ_ID_MASK; 86099ecfbf8SJan Medala 861b68309beSRafal Kozik ENA_REG_WRITE32(ena_dev->bus, mmio_read_reg, 862b68309beSRafal Kozik ena_dev->reg_bar + ENA_REGS_MMIO_REG_READ_OFF); 86399ecfbf8SJan Medala 8643adcba9aSMichal Krawczyk for (i = 0; i < timeout; i++) { 865b68309beSRafal Kozik if (READ_ONCE16(read_resp->req_id) == mmio_read->seq_num) 86699ecfbf8SJan Medala break; 86799ecfbf8SJan Medala 86899ecfbf8SJan Medala ENA_UDELAY(1); 86999ecfbf8SJan Medala } 87099ecfbf8SJan Medala 8713adcba9aSMichal Krawczyk if (unlikely(i == timeout)) { 872f73f53f7SShai Brandes ena_trc_err(ena_dev, "Reading reg failed for timeout. expected: req id[%u] offset[%u] actual: req id[%u] offset[%u]\n", 87399ecfbf8SJan Medala mmio_read->seq_num, 87499ecfbf8SJan Medala offset, 87599ecfbf8SJan Medala read_resp->req_id, 87699ecfbf8SJan Medala read_resp->reg_off); 87799ecfbf8SJan Medala ret = ENA_MMIO_READ_TIMEOUT; 87899ecfbf8SJan Medala goto err; 87999ecfbf8SJan Medala } 88099ecfbf8SJan Medala 8816dcee7cdSJan Medala if (read_resp->reg_off != offset) { 882ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Read failure: wrong offset provided\n"); 8836dcee7cdSJan Medala ret = ENA_MMIO_READ_TIMEOUT; 8846dcee7cdSJan Medala } else { 88599ecfbf8SJan Medala ret = read_resp->reg_val; 8866dcee7cdSJan Medala } 88799ecfbf8SJan Medala err: 88899ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(mmio_read->lock, flags); 88999ecfbf8SJan Medala 89099ecfbf8SJan Medala return ret; 89199ecfbf8SJan Medala } 89299ecfbf8SJan Medala 89399ecfbf8SJan Medala /* There are two types to wait for completion. 89499ecfbf8SJan Medala * Polling mode - wait until the completion is available. 89599ecfbf8SJan Medala * Async mode - wait on wait queue until the completion is ready 89699ecfbf8SJan Medala * (or the timeout expired). 89799ecfbf8SJan Medala * It is expected that the IRQ called ena_com_handle_admin_completion 89899ecfbf8SJan Medala * to mark the completions. 89999ecfbf8SJan Medala */ 9003adcba9aSMichal Krawczyk static int ena_com_wait_and_process_admin_cq(struct ena_comp_ctx *comp_ctx, 90199ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue) 90299ecfbf8SJan Medala { 90399ecfbf8SJan Medala if (admin_queue->polling) 90499ecfbf8SJan Medala return ena_com_wait_and_process_admin_cq_polling(comp_ctx, 90599ecfbf8SJan Medala admin_queue); 90699ecfbf8SJan Medala 90799ecfbf8SJan Medala return ena_com_wait_and_process_admin_cq_interrupts(comp_ctx, 90899ecfbf8SJan Medala admin_queue); 90999ecfbf8SJan Medala } 91099ecfbf8SJan Medala 91199ecfbf8SJan Medala static int ena_com_destroy_io_sq(struct ena_com_dev *ena_dev, 91299ecfbf8SJan Medala struct ena_com_io_sq *io_sq) 91399ecfbf8SJan Medala { 91499ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 91599ecfbf8SJan Medala struct ena_admin_aq_destroy_sq_cmd destroy_cmd; 91699ecfbf8SJan Medala struct ena_admin_acq_destroy_sq_resp_desc destroy_resp; 91799ecfbf8SJan Medala u8 direction; 91899ecfbf8SJan Medala int ret; 91999ecfbf8SJan Medala 9203adcba9aSMichal Krawczyk memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); 92199ecfbf8SJan Medala 92299ecfbf8SJan Medala if (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) 92399ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_TX; 92499ecfbf8SJan Medala else 92599ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_RX; 92699ecfbf8SJan Medala 92799ecfbf8SJan Medala destroy_cmd.sq.sq_identity |= (direction << 92899ecfbf8SJan Medala ENA_ADMIN_SQ_SQ_DIRECTION_SHIFT) & 92999ecfbf8SJan Medala ENA_ADMIN_SQ_SQ_DIRECTION_MASK; 93099ecfbf8SJan Medala 93199ecfbf8SJan Medala destroy_cmd.sq.sq_idx = io_sq->idx; 93299ecfbf8SJan Medala destroy_cmd.aq_common_descriptor.opcode = ENA_ADMIN_DESTROY_SQ; 93399ecfbf8SJan Medala 9343adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 93599ecfbf8SJan Medala (struct ena_admin_aq_entry *)&destroy_cmd, 93699ecfbf8SJan Medala sizeof(destroy_cmd), 93799ecfbf8SJan Medala (struct ena_admin_acq_entry *)&destroy_resp, 93899ecfbf8SJan Medala sizeof(destroy_resp)); 93999ecfbf8SJan Medala 94099ecfbf8SJan Medala if (unlikely(ret && (ret != ENA_COM_NO_DEVICE))) 941ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to destroy io sq error: %d\n", ret); 94299ecfbf8SJan Medala 94399ecfbf8SJan Medala return ret; 94499ecfbf8SJan Medala } 94599ecfbf8SJan Medala 94699ecfbf8SJan Medala static void ena_com_io_queue_free(struct ena_com_dev *ena_dev, 94799ecfbf8SJan Medala struct ena_com_io_sq *io_sq, 94899ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 94999ecfbf8SJan Medala { 95099ecfbf8SJan Medala size_t size; 95199ecfbf8SJan Medala 95299ecfbf8SJan Medala if (io_cq->cdesc_addr.virt_addr) { 95399ecfbf8SJan Medala size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth; 95499ecfbf8SJan Medala 95599ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 95699ecfbf8SJan Medala size, 95799ecfbf8SJan Medala io_cq->cdesc_addr.virt_addr, 95899ecfbf8SJan Medala io_cq->cdesc_addr.phys_addr, 95999ecfbf8SJan Medala io_cq->cdesc_addr.mem_handle); 96099ecfbf8SJan Medala 96199ecfbf8SJan Medala io_cq->cdesc_addr.virt_addr = NULL; 96299ecfbf8SJan Medala } 96399ecfbf8SJan Medala 96499ecfbf8SJan Medala if (io_sq->desc_addr.virt_addr) { 96599ecfbf8SJan Medala size = io_sq->desc_entry_size * io_sq->q_depth; 96699ecfbf8SJan Medala 96799ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 96899ecfbf8SJan Medala size, 96999ecfbf8SJan Medala io_sq->desc_addr.virt_addr, 97099ecfbf8SJan Medala io_sq->desc_addr.phys_addr, 97199ecfbf8SJan Medala io_sq->desc_addr.mem_handle); 97299ecfbf8SJan Medala 97399ecfbf8SJan Medala io_sq->desc_addr.virt_addr = NULL; 97499ecfbf8SJan Medala } 975b68309beSRafal Kozik 976b68309beSRafal Kozik if (io_sq->bounce_buf_ctrl.base_buffer) { 977b2b02edeSMichal Krawczyk ENA_MEM_FREE(ena_dev->dmadev, 978b2b02edeSMichal Krawczyk io_sq->bounce_buf_ctrl.base_buffer, 979b2b02edeSMichal Krawczyk (io_sq->llq_info.desc_list_entry_size * ENA_COM_BOUNCE_BUFFER_CNTRL_CNT)); 980b68309beSRafal Kozik io_sq->bounce_buf_ctrl.base_buffer = NULL; 981b68309beSRafal Kozik } 98299ecfbf8SJan Medala } 98399ecfbf8SJan Medala 9843adcba9aSMichal Krawczyk static int wait_for_reset_state(struct ena_com_dev *ena_dev, u32 timeout, 9853adcba9aSMichal Krawczyk u16 exp_state) 98699ecfbf8SJan Medala { 9870c84e048SMichal Krawczyk u32 val, exp = 0; 9880c84e048SMichal Krawczyk ena_time_t timeout_stamp; 98999ecfbf8SJan Medala 9900c84e048SMichal Krawczyk /* Convert timeout from resolution of 100ms to us resolution. */ 9910c84e048SMichal Krawczyk timeout_stamp = ENA_GET_SYSTEM_TIMEOUT(100 * 1000 * timeout); 9923adcba9aSMichal Krawczyk 9930c84e048SMichal Krawczyk while (1) { 99499ecfbf8SJan Medala val = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF); 99599ecfbf8SJan Medala 99699ecfbf8SJan Medala if (unlikely(val == ENA_MMIO_READ_TIMEOUT)) { 997ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reg read timeout occurred\n"); 99899ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 99999ecfbf8SJan Medala } 100099ecfbf8SJan Medala 100199ecfbf8SJan Medala if ((val & ENA_REGS_DEV_STS_RESET_IN_PROGRESS_MASK) == 100299ecfbf8SJan Medala exp_state) 100399ecfbf8SJan Medala return 0; 100499ecfbf8SJan Medala 10050c84e048SMichal Krawczyk if (ENA_TIME_EXPIRE(timeout_stamp)) 100699ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 10070c84e048SMichal Krawczyk 10080c84e048SMichal Krawczyk ena_delay_exponential_backoff_us(exp++, ena_dev->ena_min_poll_delay_us); 10090c84e048SMichal Krawczyk } 101099ecfbf8SJan Medala } 101199ecfbf8SJan Medala 10123adcba9aSMichal Krawczyk static bool ena_com_check_supported_feature_id(struct ena_com_dev *ena_dev, 101399ecfbf8SJan Medala enum ena_admin_aq_feature_id feature_id) 101499ecfbf8SJan Medala { 101599ecfbf8SJan Medala u32 feature_mask = 1 << feature_id; 101699ecfbf8SJan Medala 101799ecfbf8SJan Medala /* Device attributes is always supported */ 101899ecfbf8SJan Medala if ((feature_id != ENA_ADMIN_DEVICE_ATTRIBUTES) && 101999ecfbf8SJan Medala !(ena_dev->supported_features & feature_mask)) 102099ecfbf8SJan Medala return false; 102199ecfbf8SJan Medala 102299ecfbf8SJan Medala return true; 102399ecfbf8SJan Medala } 102499ecfbf8SJan Medala 102599ecfbf8SJan Medala static int ena_com_get_feature_ex(struct ena_com_dev *ena_dev, 102699ecfbf8SJan Medala struct ena_admin_get_feat_resp *get_resp, 102799ecfbf8SJan Medala enum ena_admin_aq_feature_id feature_id, 102899ecfbf8SJan Medala dma_addr_t control_buf_dma_addr, 1029b68309beSRafal Kozik u32 control_buff_size, 1030b68309beSRafal Kozik u8 feature_ver) 103199ecfbf8SJan Medala { 103299ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 103399ecfbf8SJan Medala struct ena_admin_get_feat_cmd get_cmd; 103499ecfbf8SJan Medala int ret; 103599ecfbf8SJan Medala 103699ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, feature_id)) { 1037ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Feature %d isn't supported\n", feature_id); 10383adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 103999ecfbf8SJan Medala } 104099ecfbf8SJan Medala 104199ecfbf8SJan Medala memset(&get_cmd, 0x0, sizeof(get_cmd)); 104299ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 104399ecfbf8SJan Medala 104499ecfbf8SJan Medala get_cmd.aq_common_descriptor.opcode = ENA_ADMIN_GET_FEATURE; 104599ecfbf8SJan Medala 104699ecfbf8SJan Medala if (control_buff_size) 104799ecfbf8SJan Medala get_cmd.aq_common_descriptor.flags = 104899ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 104999ecfbf8SJan Medala else 105099ecfbf8SJan Medala get_cmd.aq_common_descriptor.flags = 0; 105199ecfbf8SJan Medala 105299ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 105399ecfbf8SJan Medala &get_cmd.control_buffer.address, 105499ecfbf8SJan Medala control_buf_dma_addr); 105599ecfbf8SJan Medala if (unlikely(ret)) { 1056ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 105799ecfbf8SJan Medala return ret; 105899ecfbf8SJan Medala } 105999ecfbf8SJan Medala 106099ecfbf8SJan Medala get_cmd.control_buffer.length = control_buff_size; 1061b68309beSRafal Kozik get_cmd.feat_common.feature_version = feature_ver; 106299ecfbf8SJan Medala get_cmd.feat_common.feature_id = feature_id; 106399ecfbf8SJan Medala 106499ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 106599ecfbf8SJan Medala (struct ena_admin_aq_entry *) 106699ecfbf8SJan Medala &get_cmd, 106799ecfbf8SJan Medala sizeof(get_cmd), 106899ecfbf8SJan Medala (struct ena_admin_acq_entry *) 106999ecfbf8SJan Medala get_resp, 107099ecfbf8SJan Medala sizeof(*get_resp)); 107199ecfbf8SJan Medala 107299ecfbf8SJan Medala if (unlikely(ret)) 1073ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to submit get_feature command %d error: %d\n", 107499ecfbf8SJan Medala feature_id, ret); 107599ecfbf8SJan Medala 107699ecfbf8SJan Medala return ret; 107799ecfbf8SJan Medala } 107899ecfbf8SJan Medala 107999ecfbf8SJan Medala static int ena_com_get_feature(struct ena_com_dev *ena_dev, 108099ecfbf8SJan Medala struct ena_admin_get_feat_resp *get_resp, 1081b68309beSRafal Kozik enum ena_admin_aq_feature_id feature_id, 1082b68309beSRafal Kozik u8 feature_ver) 108399ecfbf8SJan Medala { 108499ecfbf8SJan Medala return ena_com_get_feature_ex(ena_dev, 108599ecfbf8SJan Medala get_resp, 108699ecfbf8SJan Medala feature_id, 108799ecfbf8SJan Medala 0, 1088b68309beSRafal Kozik 0, 1089b68309beSRafal Kozik feature_ver); 109099ecfbf8SJan Medala } 109199ecfbf8SJan Medala 10923e55684eSMichal Krawczyk int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev) 10933e55684eSMichal Krawczyk { 10943e55684eSMichal Krawczyk return ena_dev->rss.hash_func; 10953e55684eSMichal Krawczyk } 10963e55684eSMichal Krawczyk 1097086c6b66SMichal Krawczyk static void ena_com_hash_key_fill_default_key(struct ena_com_dev *ena_dev) 1098086c6b66SMichal Krawczyk { 1099086c6b66SMichal Krawczyk struct ena_admin_feature_rss_flow_hash_control *hash_key = 1100086c6b66SMichal Krawczyk (ena_dev->rss).hash_key; 1101086c6b66SMichal Krawczyk 1102086c6b66SMichal Krawczyk ENA_RSS_FILL_KEY(&hash_key->key, sizeof(hash_key->key)); 1103720854c9SMichal Krawczyk /* The key buffer is stored in the device in an array of 1104720854c9SMichal Krawczyk * uint32 elements. 1105086c6b66SMichal Krawczyk */ 1106b19f366cSMichal Krawczyk hash_key->key_parts = ENA_ADMIN_RSS_KEY_PARTS; 1107086c6b66SMichal Krawczyk } 1108086c6b66SMichal Krawczyk 110999ecfbf8SJan Medala static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev) 111099ecfbf8SJan Medala { 111199ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 111299ecfbf8SJan Medala 1113ff40db8dSMichal Krawczyk if (!ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_RSS_HASH_FUNCTION)) 1114ff40db8dSMichal Krawczyk return ENA_COM_UNSUPPORTED; 1115ff40db8dSMichal Krawczyk 111699ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 111799ecfbf8SJan Medala sizeof(*rss->hash_key), 111899ecfbf8SJan Medala rss->hash_key, 111999ecfbf8SJan Medala rss->hash_key_dma_addr, 112099ecfbf8SJan Medala rss->hash_key_mem_handle); 112199ecfbf8SJan Medala 112299ecfbf8SJan Medala if (unlikely(!rss->hash_key)) 112399ecfbf8SJan Medala return ENA_COM_NO_MEM; 112499ecfbf8SJan Medala 112599ecfbf8SJan Medala return 0; 112699ecfbf8SJan Medala } 112799ecfbf8SJan Medala 11286dcee7cdSJan Medala static void ena_com_hash_key_destroy(struct ena_com_dev *ena_dev) 112999ecfbf8SJan Medala { 113099ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 113199ecfbf8SJan Medala 113299ecfbf8SJan Medala if (rss->hash_key) 113399ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 113499ecfbf8SJan Medala sizeof(*rss->hash_key), 113599ecfbf8SJan Medala rss->hash_key, 113699ecfbf8SJan Medala rss->hash_key_dma_addr, 113799ecfbf8SJan Medala rss->hash_key_mem_handle); 113899ecfbf8SJan Medala rss->hash_key = NULL; 113999ecfbf8SJan Medala } 114099ecfbf8SJan Medala 114199ecfbf8SJan Medala static int ena_com_hash_ctrl_init(struct ena_com_dev *ena_dev) 114299ecfbf8SJan Medala { 114399ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 114499ecfbf8SJan Medala 114599ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 114699ecfbf8SJan Medala sizeof(*rss->hash_ctrl), 114799ecfbf8SJan Medala rss->hash_ctrl, 114899ecfbf8SJan Medala rss->hash_ctrl_dma_addr, 114999ecfbf8SJan Medala rss->hash_ctrl_mem_handle); 115099ecfbf8SJan Medala 11516dcee7cdSJan Medala if (unlikely(!rss->hash_ctrl)) 11526dcee7cdSJan Medala return ENA_COM_NO_MEM; 11536dcee7cdSJan Medala 115499ecfbf8SJan Medala return 0; 115599ecfbf8SJan Medala } 115699ecfbf8SJan Medala 11576dcee7cdSJan Medala static void ena_com_hash_ctrl_destroy(struct ena_com_dev *ena_dev) 115899ecfbf8SJan Medala { 115999ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 116099ecfbf8SJan Medala 116199ecfbf8SJan Medala if (rss->hash_ctrl) 116299ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 116399ecfbf8SJan Medala sizeof(*rss->hash_ctrl), 116499ecfbf8SJan Medala rss->hash_ctrl, 116599ecfbf8SJan Medala rss->hash_ctrl_dma_addr, 116699ecfbf8SJan Medala rss->hash_ctrl_mem_handle); 116799ecfbf8SJan Medala rss->hash_ctrl = NULL; 116899ecfbf8SJan Medala } 116999ecfbf8SJan Medala 117099ecfbf8SJan Medala static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev, 117199ecfbf8SJan Medala u16 log_size) 117299ecfbf8SJan Medala { 117399ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 117499ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 117599ecfbf8SJan Medala size_t tbl_size; 117699ecfbf8SJan Medala int ret; 117799ecfbf8SJan Medala 117899ecfbf8SJan Medala ret = ena_com_get_feature(ena_dev, &get_resp, 1179b19f366cSMichal Krawczyk ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG, 0); 118099ecfbf8SJan Medala if (unlikely(ret)) 118199ecfbf8SJan Medala return ret; 118299ecfbf8SJan Medala 118399ecfbf8SJan Medala if ((get_resp.u.ind_table.min_size > log_size) || 118499ecfbf8SJan Medala (get_resp.u.ind_table.max_size < log_size)) { 1185ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Indirect table size doesn't fit. requested size: %d while min is:%d and max %d\n", 118699ecfbf8SJan Medala 1 << log_size, 118799ecfbf8SJan Medala 1 << get_resp.u.ind_table.min_size, 118899ecfbf8SJan Medala 1 << get_resp.u.ind_table.max_size); 118999ecfbf8SJan Medala return ENA_COM_INVAL; 119099ecfbf8SJan Medala } 119199ecfbf8SJan Medala 11926dcee7cdSJan Medala tbl_size = (1ULL << log_size) * 119399ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 119499ecfbf8SJan Medala 119599ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 119699ecfbf8SJan Medala tbl_size, 119799ecfbf8SJan Medala rss->rss_ind_tbl, 119899ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 119999ecfbf8SJan Medala rss->rss_ind_tbl_mem_handle); 120099ecfbf8SJan Medala if (unlikely(!rss->rss_ind_tbl)) 120199ecfbf8SJan Medala goto mem_err1; 120299ecfbf8SJan Medala 12036dcee7cdSJan Medala tbl_size = (1ULL << log_size) * sizeof(u16); 120499ecfbf8SJan Medala rss->host_rss_ind_tbl = 120599ecfbf8SJan Medala ENA_MEM_ALLOC(ena_dev->dmadev, tbl_size); 120699ecfbf8SJan Medala if (unlikely(!rss->host_rss_ind_tbl)) 120799ecfbf8SJan Medala goto mem_err2; 120899ecfbf8SJan Medala 120999ecfbf8SJan Medala rss->tbl_log_size = log_size; 121099ecfbf8SJan Medala 121199ecfbf8SJan Medala return 0; 121299ecfbf8SJan Medala 121399ecfbf8SJan Medala mem_err2: 12146dcee7cdSJan Medala tbl_size = (1ULL << log_size) * 121599ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 121699ecfbf8SJan Medala 121799ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 121899ecfbf8SJan Medala tbl_size, 121999ecfbf8SJan Medala rss->rss_ind_tbl, 122099ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 122199ecfbf8SJan Medala rss->rss_ind_tbl_mem_handle); 122299ecfbf8SJan Medala rss->rss_ind_tbl = NULL; 122399ecfbf8SJan Medala mem_err1: 122499ecfbf8SJan Medala rss->tbl_log_size = 0; 122599ecfbf8SJan Medala return ENA_COM_NO_MEM; 122699ecfbf8SJan Medala } 122799ecfbf8SJan Medala 12286dcee7cdSJan Medala static void ena_com_indirect_table_destroy(struct ena_com_dev *ena_dev) 122999ecfbf8SJan Medala { 123099ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 12316dcee7cdSJan Medala size_t tbl_size = (1ULL << rss->tbl_log_size) * 123299ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 123399ecfbf8SJan Medala 123499ecfbf8SJan Medala if (rss->rss_ind_tbl) 123599ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 123699ecfbf8SJan Medala tbl_size, 123799ecfbf8SJan Medala rss->rss_ind_tbl, 123899ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 123999ecfbf8SJan Medala rss->rss_ind_tbl_mem_handle); 124099ecfbf8SJan Medala rss->rss_ind_tbl = NULL; 124199ecfbf8SJan Medala 124299ecfbf8SJan Medala if (rss->host_rss_ind_tbl) 1243b2b02edeSMichal Krawczyk ENA_MEM_FREE(ena_dev->dmadev, 1244b2b02edeSMichal Krawczyk rss->host_rss_ind_tbl, 1245b2b02edeSMichal Krawczyk ((1ULL << rss->tbl_log_size) * sizeof(u16))); 124699ecfbf8SJan Medala rss->host_rss_ind_tbl = NULL; 124799ecfbf8SJan Medala } 124899ecfbf8SJan Medala 124999ecfbf8SJan Medala static int ena_com_create_io_sq(struct ena_com_dev *ena_dev, 125099ecfbf8SJan Medala struct ena_com_io_sq *io_sq, u16 cq_idx) 125199ecfbf8SJan Medala { 125299ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 125399ecfbf8SJan Medala struct ena_admin_aq_create_sq_cmd create_cmd; 125499ecfbf8SJan Medala struct ena_admin_acq_create_sq_resp_desc cmd_completion; 125599ecfbf8SJan Medala u8 direction; 125699ecfbf8SJan Medala int ret; 125799ecfbf8SJan Medala 12583adcba9aSMichal Krawczyk memset(&create_cmd, 0x0, sizeof(create_cmd)); 125999ecfbf8SJan Medala 126099ecfbf8SJan Medala create_cmd.aq_common_descriptor.opcode = ENA_ADMIN_CREATE_SQ; 126199ecfbf8SJan Medala 126299ecfbf8SJan Medala if (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) 126399ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_TX; 126499ecfbf8SJan Medala else 126599ecfbf8SJan Medala direction = ENA_ADMIN_SQ_DIRECTION_RX; 126699ecfbf8SJan Medala 126799ecfbf8SJan Medala create_cmd.sq_identity |= (direction << 126899ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_SQ_DIRECTION_SHIFT) & 126999ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_SQ_DIRECTION_MASK; 127099ecfbf8SJan Medala 127199ecfbf8SJan Medala create_cmd.sq_caps_2 |= io_sq->mem_queue_type & 127299ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_PLACEMENT_POLICY_MASK; 127399ecfbf8SJan Medala 127499ecfbf8SJan Medala create_cmd.sq_caps_2 |= (ENA_ADMIN_COMPLETION_POLICY_DESC << 127599ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_COMPLETION_POLICY_SHIFT) & 127699ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_COMPLETION_POLICY_MASK; 127799ecfbf8SJan Medala 127899ecfbf8SJan Medala create_cmd.sq_caps_3 |= 127999ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_SQ_CMD_IS_PHYSICALLY_CONTIGUOUS_MASK; 128099ecfbf8SJan Medala 128199ecfbf8SJan Medala create_cmd.cq_idx = cq_idx; 128299ecfbf8SJan Medala create_cmd.sq_depth = io_sq->q_depth; 128399ecfbf8SJan Medala 128499ecfbf8SJan Medala if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) { 128599ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 128699ecfbf8SJan Medala &create_cmd.sq_ba, 128799ecfbf8SJan Medala io_sq->desc_addr.phys_addr); 128899ecfbf8SJan Medala if (unlikely(ret)) { 1289ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 129099ecfbf8SJan Medala return ret; 129199ecfbf8SJan Medala } 129299ecfbf8SJan Medala } 129399ecfbf8SJan Medala 12943adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 129599ecfbf8SJan Medala (struct ena_admin_aq_entry *)&create_cmd, 129699ecfbf8SJan Medala sizeof(create_cmd), 129799ecfbf8SJan Medala (struct ena_admin_acq_entry *)&cmd_completion, 129899ecfbf8SJan Medala sizeof(cmd_completion)); 129999ecfbf8SJan Medala if (unlikely(ret)) { 1300ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to create IO SQ. error: %d\n", ret); 130199ecfbf8SJan Medala return ret; 130299ecfbf8SJan Medala } 130399ecfbf8SJan Medala 130499ecfbf8SJan Medala io_sq->idx = cmd_completion.sq_idx; 130599ecfbf8SJan Medala 130699ecfbf8SJan Medala io_sq->db_addr = (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 130799ecfbf8SJan Medala (uintptr_t)cmd_completion.sq_doorbell_offset); 130899ecfbf8SJan Medala 130999ecfbf8SJan Medala if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { 131099ecfbf8SJan Medala io_sq->desc_addr.pbuf_dev_addr = 131199ecfbf8SJan Medala (u8 __iomem *)((uintptr_t)ena_dev->mem_bar + 131299ecfbf8SJan Medala cmd_completion.llq_descriptors_offset); 131399ecfbf8SJan Medala } 131499ecfbf8SJan Medala 1315ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Created sq[%u], depth[%u]\n", io_sq->idx, io_sq->q_depth); 131699ecfbf8SJan Medala 131799ecfbf8SJan Medala return ret; 131899ecfbf8SJan Medala } 131999ecfbf8SJan Medala 132099ecfbf8SJan Medala static int ena_com_ind_tbl_convert_to_device(struct ena_com_dev *ena_dev) 132199ecfbf8SJan Medala { 132299ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 132399ecfbf8SJan Medala struct ena_com_io_sq *io_sq; 132499ecfbf8SJan Medala u16 qid; 132599ecfbf8SJan Medala int i; 132699ecfbf8SJan Medala 132799ecfbf8SJan Medala for (i = 0; i < 1 << rss->tbl_log_size; i++) { 132899ecfbf8SJan Medala qid = rss->host_rss_ind_tbl[i]; 132999ecfbf8SJan Medala if (qid >= ENA_TOTAL_NUM_QUEUES) 133099ecfbf8SJan Medala return ENA_COM_INVAL; 133199ecfbf8SJan Medala 133299ecfbf8SJan Medala io_sq = &ena_dev->io_sq_queues[qid]; 133399ecfbf8SJan Medala 133499ecfbf8SJan Medala if (io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX) 133599ecfbf8SJan Medala return ENA_COM_INVAL; 133699ecfbf8SJan Medala 133799ecfbf8SJan Medala rss->rss_ind_tbl[i].cq_idx = io_sq->idx; 133899ecfbf8SJan Medala } 133999ecfbf8SJan Medala 134099ecfbf8SJan Medala return 0; 134199ecfbf8SJan Medala } 134299ecfbf8SJan Medala 13433adcba9aSMichal Krawczyk static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev, 13446dcee7cdSJan Medala u16 intr_delay_resolution) 134599ecfbf8SJan Medala { 1346d2138b23SMichal Krawczyk u16 prev_intr_delay_resolution = ena_dev->intr_delay_resolution; 134799ecfbf8SJan Medala 1348d2138b23SMichal Krawczyk if (unlikely(!intr_delay_resolution)) { 1349ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Illegal intr_delay_resolution provided. Going to use default 1 usec resolution\n"); 1350d2138b23SMichal Krawczyk intr_delay_resolution = ENA_DEFAULT_INTR_DELAY_RESOLUTION; 135199ecfbf8SJan Medala } 135299ecfbf8SJan Medala 135399ecfbf8SJan Medala /* update Rx */ 1354d2138b23SMichal Krawczyk ena_dev->intr_moder_rx_interval = 1355d2138b23SMichal Krawczyk ena_dev->intr_moder_rx_interval * 1356d2138b23SMichal Krawczyk prev_intr_delay_resolution / 1357d2138b23SMichal Krawczyk intr_delay_resolution; 135899ecfbf8SJan Medala 135999ecfbf8SJan Medala /* update Tx */ 1360d2138b23SMichal Krawczyk ena_dev->intr_moder_tx_interval = 1361d2138b23SMichal Krawczyk ena_dev->intr_moder_tx_interval * 1362d2138b23SMichal Krawczyk prev_intr_delay_resolution / 1363d2138b23SMichal Krawczyk intr_delay_resolution; 1364d2138b23SMichal Krawczyk 1365d2138b23SMichal Krawczyk ena_dev->intr_delay_resolution = intr_delay_resolution; 136699ecfbf8SJan Medala } 136799ecfbf8SJan Medala 136899ecfbf8SJan Medala /*****************************************************************************/ 136999ecfbf8SJan Medala /******************************* API ******************************/ 137099ecfbf8SJan Medala /*****************************************************************************/ 137199ecfbf8SJan Medala 137299ecfbf8SJan Medala int ena_com_execute_admin_command(struct ena_com_admin_queue *admin_queue, 137399ecfbf8SJan Medala struct ena_admin_aq_entry *cmd, 137499ecfbf8SJan Medala size_t cmd_size, 137599ecfbf8SJan Medala struct ena_admin_acq_entry *comp, 137699ecfbf8SJan Medala size_t comp_size) 137799ecfbf8SJan Medala { 137899ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 13793adcba9aSMichal Krawczyk int ret; 138099ecfbf8SJan Medala 138199ecfbf8SJan Medala comp_ctx = ena_com_submit_admin_cmd(admin_queue, cmd, cmd_size, 138299ecfbf8SJan Medala comp, comp_size); 13833adcba9aSMichal Krawczyk if (IS_ERR(comp_ctx)) { 1384f73f53f7SShai Brandes ret = PTR_ERR(comp_ctx); 1385f73f53f7SShai Brandes if (ret == ENA_COM_NO_DEVICE) 1386ac2fd8a5SMichal Krawczyk ena_trc_dbg(admin_queue->ena_dev, 1387f73f53f7SShai Brandes "Failed to submit command [%d]\n", 1388f73f53f7SShai Brandes ret); 13893adcba9aSMichal Krawczyk else 1390ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 1391f73f53f7SShai Brandes "Failed to submit command [%d]\n", 1392f73f53f7SShai Brandes ret); 13933adcba9aSMichal Krawczyk 1394f73f53f7SShai Brandes return ret; 139599ecfbf8SJan Medala } 139699ecfbf8SJan Medala 139799ecfbf8SJan Medala ret = ena_com_wait_and_process_admin_cq(comp_ctx, admin_queue); 139899ecfbf8SJan Medala if (unlikely(ret)) { 139999ecfbf8SJan Medala if (admin_queue->running_state) 1400ac2fd8a5SMichal Krawczyk ena_trc_err(admin_queue->ena_dev, 1401ac2fd8a5SMichal Krawczyk "Failed to process command. ret = %d\n", ret); 140299ecfbf8SJan Medala else 1403ac2fd8a5SMichal Krawczyk ena_trc_dbg(admin_queue->ena_dev, 1404ac2fd8a5SMichal Krawczyk "Failed to process command. ret = %d\n", ret); 140599ecfbf8SJan Medala } 140699ecfbf8SJan Medala return ret; 140799ecfbf8SJan Medala } 140899ecfbf8SJan Medala 140999ecfbf8SJan Medala int ena_com_create_io_cq(struct ena_com_dev *ena_dev, 141099ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 141199ecfbf8SJan Medala { 141299ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 141399ecfbf8SJan Medala struct ena_admin_aq_create_cq_cmd create_cmd; 141499ecfbf8SJan Medala struct ena_admin_acq_create_cq_resp_desc cmd_completion; 141599ecfbf8SJan Medala int ret; 141699ecfbf8SJan Medala 14173adcba9aSMichal Krawczyk memset(&create_cmd, 0x0, sizeof(create_cmd)); 141899ecfbf8SJan Medala 141999ecfbf8SJan Medala create_cmd.aq_common_descriptor.opcode = ENA_ADMIN_CREATE_CQ; 142099ecfbf8SJan Medala 142199ecfbf8SJan Medala create_cmd.cq_caps_2 |= (io_cq->cdesc_entry_size_in_bytes / 4) & 142299ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; 142399ecfbf8SJan Medala create_cmd.cq_caps_1 |= 142499ecfbf8SJan Medala ENA_ADMIN_AQ_CREATE_CQ_CMD_INTERRUPT_MODE_ENABLED_MASK; 142599ecfbf8SJan Medala 142699ecfbf8SJan Medala create_cmd.msix_vector = io_cq->msix_vector; 142799ecfbf8SJan Medala create_cmd.cq_depth = io_cq->q_depth; 142899ecfbf8SJan Medala 142999ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 143099ecfbf8SJan Medala &create_cmd.cq_ba, 143199ecfbf8SJan Medala io_cq->cdesc_addr.phys_addr); 143299ecfbf8SJan Medala if (unlikely(ret)) { 1433ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 143499ecfbf8SJan Medala return ret; 143599ecfbf8SJan Medala } 143699ecfbf8SJan Medala 14373adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 143899ecfbf8SJan Medala (struct ena_admin_aq_entry *)&create_cmd, 143999ecfbf8SJan Medala sizeof(create_cmd), 144099ecfbf8SJan Medala (struct ena_admin_acq_entry *)&cmd_completion, 144199ecfbf8SJan Medala sizeof(cmd_completion)); 144299ecfbf8SJan Medala if (unlikely(ret)) { 1443ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to create IO CQ. error: %d\n", ret); 144499ecfbf8SJan Medala return ret; 144599ecfbf8SJan Medala } 144699ecfbf8SJan Medala 144799ecfbf8SJan Medala io_cq->idx = cmd_completion.cq_idx; 144899ecfbf8SJan Medala 144999ecfbf8SJan Medala io_cq->unmask_reg = (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 14506dcee7cdSJan Medala cmd_completion.cq_interrupt_unmask_register_offset); 145199ecfbf8SJan Medala 14526dcee7cdSJan Medala if (cmd_completion.numa_node_register_offset) 14536dcee7cdSJan Medala io_cq->numa_node_cfg_reg = 14546dcee7cdSJan Medala (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 14556dcee7cdSJan Medala cmd_completion.numa_node_register_offset); 145699ecfbf8SJan Medala 1457ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Created cq[%u], depth[%u]\n", io_cq->idx, io_cq->q_depth); 145899ecfbf8SJan Medala 145999ecfbf8SJan Medala return ret; 146099ecfbf8SJan Medala } 146199ecfbf8SJan Medala 146299ecfbf8SJan Medala int ena_com_get_io_handlers(struct ena_com_dev *ena_dev, u16 qid, 146399ecfbf8SJan Medala struct ena_com_io_sq **io_sq, 146499ecfbf8SJan Medala struct ena_com_io_cq **io_cq) 146599ecfbf8SJan Medala { 146699ecfbf8SJan Medala if (qid >= ENA_TOTAL_NUM_QUEUES) { 1467ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid queue number %d but the max is %d\n", 146899ecfbf8SJan Medala qid, ENA_TOTAL_NUM_QUEUES); 146999ecfbf8SJan Medala return ENA_COM_INVAL; 147099ecfbf8SJan Medala } 147199ecfbf8SJan Medala 147299ecfbf8SJan Medala *io_sq = &ena_dev->io_sq_queues[qid]; 147399ecfbf8SJan Medala *io_cq = &ena_dev->io_cq_queues[qid]; 147499ecfbf8SJan Medala 147599ecfbf8SJan Medala return 0; 147699ecfbf8SJan Medala } 147799ecfbf8SJan Medala 147899ecfbf8SJan Medala void ena_com_abort_admin_commands(struct ena_com_dev *ena_dev) 147999ecfbf8SJan Medala { 148099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 148199ecfbf8SJan Medala struct ena_comp_ctx *comp_ctx; 148299ecfbf8SJan Medala u16 i; 148399ecfbf8SJan Medala 148499ecfbf8SJan Medala if (!admin_queue->comp_ctx) 148599ecfbf8SJan Medala return; 148699ecfbf8SJan Medala 148799ecfbf8SJan Medala for (i = 0; i < admin_queue->q_depth; i++) { 148899ecfbf8SJan Medala comp_ctx = get_comp_ctxt(admin_queue, i, false); 14896dcee7cdSJan Medala if (unlikely(!comp_ctx)) 14906dcee7cdSJan Medala break; 14916dcee7cdSJan Medala 149299ecfbf8SJan Medala comp_ctx->status = ENA_CMD_ABORTED; 149399ecfbf8SJan Medala 149499ecfbf8SJan Medala ENA_WAIT_EVENT_SIGNAL(comp_ctx->wait_event); 149599ecfbf8SJan Medala } 149699ecfbf8SJan Medala } 149799ecfbf8SJan Medala 149899ecfbf8SJan Medala void ena_com_wait_for_abort_completion(struct ena_com_dev *ena_dev) 149999ecfbf8SJan Medala { 150099ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 150123a70746SDaniel Mrzyglod unsigned long flags = 0; 15020c84e048SMichal Krawczyk u32 exp = 0; 150399ecfbf8SJan Medala 150499ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 150599ecfbf8SJan Medala while (ATOMIC32_READ(&admin_queue->outstanding_cmds) != 0) { 150699ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 15070c84e048SMichal Krawczyk ena_delay_exponential_backoff_us(exp++, ena_dev->ena_min_poll_delay_us); 150899ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 150999ecfbf8SJan Medala } 151099ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 151199ecfbf8SJan Medala } 151299ecfbf8SJan Medala 151399ecfbf8SJan Medala int ena_com_destroy_io_cq(struct ena_com_dev *ena_dev, 151499ecfbf8SJan Medala struct ena_com_io_cq *io_cq) 151599ecfbf8SJan Medala { 151699ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 151799ecfbf8SJan Medala struct ena_admin_aq_destroy_cq_cmd destroy_cmd; 151899ecfbf8SJan Medala struct ena_admin_acq_destroy_cq_resp_desc destroy_resp; 151999ecfbf8SJan Medala int ret; 152099ecfbf8SJan Medala 15213adcba9aSMichal Krawczyk memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); 152299ecfbf8SJan Medala 152399ecfbf8SJan Medala destroy_cmd.cq_idx = io_cq->idx; 152499ecfbf8SJan Medala destroy_cmd.aq_common_descriptor.opcode = ENA_ADMIN_DESTROY_CQ; 152599ecfbf8SJan Medala 15263adcba9aSMichal Krawczyk ret = ena_com_execute_admin_command(admin_queue, 152799ecfbf8SJan Medala (struct ena_admin_aq_entry *)&destroy_cmd, 152899ecfbf8SJan Medala sizeof(destroy_cmd), 152999ecfbf8SJan Medala (struct ena_admin_acq_entry *)&destroy_resp, 153099ecfbf8SJan Medala sizeof(destroy_resp)); 153199ecfbf8SJan Medala 153299ecfbf8SJan Medala if (unlikely(ret && (ret != ENA_COM_NO_DEVICE))) 1533ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to destroy IO CQ. error: %d\n", ret); 153499ecfbf8SJan Medala 153599ecfbf8SJan Medala return ret; 153699ecfbf8SJan Medala } 153799ecfbf8SJan Medala 153899ecfbf8SJan Medala bool ena_com_get_admin_running_state(struct ena_com_dev *ena_dev) 153999ecfbf8SJan Medala { 154099ecfbf8SJan Medala return ena_dev->admin_queue.running_state; 154199ecfbf8SJan Medala } 154299ecfbf8SJan Medala 154399ecfbf8SJan Medala void ena_com_set_admin_running_state(struct ena_com_dev *ena_dev, bool state) 154499ecfbf8SJan Medala { 154599ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 154623a70746SDaniel Mrzyglod unsigned long flags = 0; 154799ecfbf8SJan Medala 154899ecfbf8SJan Medala ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags); 154999ecfbf8SJan Medala ena_dev->admin_queue.running_state = state; 155099ecfbf8SJan Medala ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags); 155199ecfbf8SJan Medala } 155299ecfbf8SJan Medala 155399ecfbf8SJan Medala void ena_com_admin_aenq_enable(struct ena_com_dev *ena_dev) 155499ecfbf8SJan Medala { 155599ecfbf8SJan Medala u16 depth = ena_dev->aenq.q_depth; 155699ecfbf8SJan Medala 1557ac2fd8a5SMichal Krawczyk ENA_WARN(ena_dev->aenq.head != depth, ena_dev, "Invalid AENQ state\n"); 155899ecfbf8SJan Medala 155999ecfbf8SJan Medala /* Init head_db to mark that all entries in the queue 156099ecfbf8SJan Medala * are initially available 156199ecfbf8SJan Medala */ 15623adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, depth, ena_dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF); 156399ecfbf8SJan Medala } 156499ecfbf8SJan Medala 156599ecfbf8SJan Medala int ena_com_set_aenq_config(struct ena_com_dev *ena_dev, u32 groups_flag) 156699ecfbf8SJan Medala { 156799ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 156899ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 156999ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 157099ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 15713adcba9aSMichal Krawczyk int ret; 157299ecfbf8SJan Medala 1573b68309beSRafal Kozik ret = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_AENQ_CONFIG, 0); 157499ecfbf8SJan Medala if (ret) { 1575ac2fd8a5SMichal Krawczyk ena_trc_info(ena_dev, "Can't get aenq configuration\n"); 157699ecfbf8SJan Medala return ret; 157799ecfbf8SJan Medala } 157899ecfbf8SJan Medala 157999ecfbf8SJan Medala if ((get_resp.u.aenq.supported_groups & groups_flag) != groups_flag) { 1580ac2fd8a5SMichal Krawczyk ena_trc_warn(ena_dev, "Trying to set unsupported aenq events. supported flag: 0x%x asked flag: 0x%x\n", 158199ecfbf8SJan Medala get_resp.u.aenq.supported_groups, 158299ecfbf8SJan Medala groups_flag); 15833adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 158499ecfbf8SJan Medala } 158599ecfbf8SJan Medala 158699ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 158799ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 158899ecfbf8SJan Medala 158999ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 159099ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 0; 159199ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_AENQ_CONFIG; 159299ecfbf8SJan Medala cmd.u.aenq.enabled_groups = groups_flag; 159399ecfbf8SJan Medala 159499ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 159599ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 159699ecfbf8SJan Medala sizeof(cmd), 159799ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 159899ecfbf8SJan Medala sizeof(resp)); 159999ecfbf8SJan Medala 160099ecfbf8SJan Medala if (unlikely(ret)) 1601ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to config AENQ ret: %d\n", ret); 160299ecfbf8SJan Medala 160399ecfbf8SJan Medala return ret; 160499ecfbf8SJan Medala } 160599ecfbf8SJan Medala 160699ecfbf8SJan Medala int ena_com_get_dma_width(struct ena_com_dev *ena_dev) 160799ecfbf8SJan Medala { 160899ecfbf8SJan Medala u32 caps = ena_com_reg_bar_read32(ena_dev, ENA_REGS_CAPS_OFF); 160983e8d537SMichal Krawczyk u32 width; 161099ecfbf8SJan Medala 161199ecfbf8SJan Medala if (unlikely(caps == ENA_MMIO_READ_TIMEOUT)) { 1612ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reg read timeout occurred\n"); 161399ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 161499ecfbf8SJan Medala } 161599ecfbf8SJan Medala 161699ecfbf8SJan Medala width = (caps & ENA_REGS_CAPS_DMA_ADDR_WIDTH_MASK) >> 161799ecfbf8SJan Medala ENA_REGS_CAPS_DMA_ADDR_WIDTH_SHIFT; 161899ecfbf8SJan Medala 1619ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "ENA dma width: %d\n", width); 162099ecfbf8SJan Medala 162199ecfbf8SJan Medala if ((width < 32) || width > ENA_MAX_PHYS_ADDR_SIZE_BITS) { 1622ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "DMA width illegal value: %d\n", width); 162399ecfbf8SJan Medala return ENA_COM_INVAL; 162499ecfbf8SJan Medala } 162599ecfbf8SJan Medala 162699ecfbf8SJan Medala ena_dev->dma_addr_bits = width; 162799ecfbf8SJan Medala 162899ecfbf8SJan Medala return width; 162999ecfbf8SJan Medala } 163099ecfbf8SJan Medala 163199ecfbf8SJan Medala int ena_com_validate_version(struct ena_com_dev *ena_dev) 163299ecfbf8SJan Medala { 163399ecfbf8SJan Medala u32 ver; 163499ecfbf8SJan Medala u32 ctrl_ver; 163599ecfbf8SJan Medala u32 ctrl_ver_masked; 163699ecfbf8SJan Medala 163799ecfbf8SJan Medala /* Make sure the ENA version and the controller version are at least 163899ecfbf8SJan Medala * as the driver expects 163999ecfbf8SJan Medala */ 164099ecfbf8SJan Medala ver = ena_com_reg_bar_read32(ena_dev, ENA_REGS_VERSION_OFF); 164199ecfbf8SJan Medala ctrl_ver = ena_com_reg_bar_read32(ena_dev, 164299ecfbf8SJan Medala ENA_REGS_CONTROLLER_VERSION_OFF); 164399ecfbf8SJan Medala 164499ecfbf8SJan Medala if (unlikely((ver == ENA_MMIO_READ_TIMEOUT) || 164599ecfbf8SJan Medala (ctrl_ver == ENA_MMIO_READ_TIMEOUT))) { 1646ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reg read timeout occurred\n"); 164799ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 164899ecfbf8SJan Medala } 164999ecfbf8SJan Medala 1650ac2fd8a5SMichal Krawczyk ena_trc_info(ena_dev, "ENA device version: %d.%d\n", 165199ecfbf8SJan Medala (ver & ENA_REGS_VERSION_MAJOR_VERSION_MASK) >> 165299ecfbf8SJan Medala ENA_REGS_VERSION_MAJOR_VERSION_SHIFT, 165399ecfbf8SJan Medala ver & ENA_REGS_VERSION_MINOR_VERSION_MASK); 165499ecfbf8SJan Medala 1655ac2fd8a5SMichal Krawczyk ena_trc_info(ena_dev, "ENA controller version: %d.%d.%d implementation version %d\n", 165699ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_MASK) 165799ecfbf8SJan Medala >> ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_SHIFT, 165899ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_MASK) 165999ecfbf8SJan Medala >> ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_SHIFT, 166099ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_SUBMINOR_VERSION_MASK), 166199ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_IMPL_ID_MASK) >> 166299ecfbf8SJan Medala ENA_REGS_CONTROLLER_VERSION_IMPL_ID_SHIFT); 166399ecfbf8SJan Medala 166499ecfbf8SJan Medala ctrl_ver_masked = 166599ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_MASK) | 166699ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_MASK) | 166799ecfbf8SJan Medala (ctrl_ver & ENA_REGS_CONTROLLER_VERSION_SUBMINOR_VERSION_MASK); 166899ecfbf8SJan Medala 166999ecfbf8SJan Medala /* Validate the ctrl version without the implementation ID */ 167099ecfbf8SJan Medala if (ctrl_ver_masked < MIN_ENA_CTRL_VER) { 1671ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "ENA ctrl version is lower than the minimal ctrl version the driver supports\n"); 167299ecfbf8SJan Medala return -1; 167399ecfbf8SJan Medala } 167499ecfbf8SJan Medala 167599ecfbf8SJan Medala return 0; 167699ecfbf8SJan Medala } 167799ecfbf8SJan Medala 167804a6a3e6SMichal Krawczyk static void 167904a6a3e6SMichal Krawczyk ena_com_free_ena_admin_queue_comp_ctx(struct ena_com_dev *ena_dev, 168004a6a3e6SMichal Krawczyk struct ena_com_admin_queue *admin_queue) 168104a6a3e6SMichal Krawczyk 168204a6a3e6SMichal Krawczyk { 168304a6a3e6SMichal Krawczyk if (!admin_queue->comp_ctx) 168404a6a3e6SMichal Krawczyk return; 168504a6a3e6SMichal Krawczyk 168604a6a3e6SMichal Krawczyk ENA_WAIT_EVENTS_DESTROY(admin_queue); 168704a6a3e6SMichal Krawczyk ENA_MEM_FREE(ena_dev->dmadev, 168804a6a3e6SMichal Krawczyk admin_queue->comp_ctx, 168904a6a3e6SMichal Krawczyk (admin_queue->q_depth * sizeof(struct ena_comp_ctx))); 169004a6a3e6SMichal Krawczyk 169104a6a3e6SMichal Krawczyk admin_queue->comp_ctx = NULL; 169204a6a3e6SMichal Krawczyk } 169304a6a3e6SMichal Krawczyk 169499ecfbf8SJan Medala void ena_com_admin_destroy(struct ena_com_dev *ena_dev) 169599ecfbf8SJan Medala { 169699ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 16973adcba9aSMichal Krawczyk struct ena_com_admin_cq *cq = &admin_queue->cq; 16983adcba9aSMichal Krawczyk struct ena_com_admin_sq *sq = &admin_queue->sq; 16993adcba9aSMichal Krawczyk struct ena_com_aenq *aenq = &ena_dev->aenq; 17003adcba9aSMichal Krawczyk u16 size; 170199ecfbf8SJan Medala 170204a6a3e6SMichal Krawczyk ena_com_free_ena_admin_queue_comp_ctx(ena_dev, admin_queue); 1703f034d4bbSMichal Krawczyk 17043adcba9aSMichal Krawczyk size = ADMIN_SQ_SIZE(admin_queue->q_depth); 17053adcba9aSMichal Krawczyk if (sq->entries) 17063adcba9aSMichal Krawczyk ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, sq->entries, 17073adcba9aSMichal Krawczyk sq->dma_addr, sq->mem_handle); 17083adcba9aSMichal Krawczyk sq->entries = NULL; 170999ecfbf8SJan Medala 17103adcba9aSMichal Krawczyk size = ADMIN_CQ_SIZE(admin_queue->q_depth); 17113adcba9aSMichal Krawczyk if (cq->entries) 17123adcba9aSMichal Krawczyk ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, cq->entries, 17133adcba9aSMichal Krawczyk cq->dma_addr, cq->mem_handle); 17143adcba9aSMichal Krawczyk cq->entries = NULL; 171599ecfbf8SJan Medala 17163adcba9aSMichal Krawczyk size = ADMIN_AENQ_SIZE(aenq->q_depth); 171799ecfbf8SJan Medala if (ena_dev->aenq.entries) 17183adcba9aSMichal Krawczyk ENA_MEM_FREE_COHERENT(ena_dev->dmadev, size, aenq->entries, 17193adcba9aSMichal Krawczyk aenq->dma_addr, aenq->mem_handle); 17203adcba9aSMichal Krawczyk aenq->entries = NULL; 1721b68309beSRafal Kozik ENA_SPINLOCK_DESTROY(admin_queue->q_lock); 172299ecfbf8SJan Medala } 172399ecfbf8SJan Medala 172499ecfbf8SJan Medala void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling) 172599ecfbf8SJan Medala { 17263adcba9aSMichal Krawczyk u32 mask_value = 0; 17273adcba9aSMichal Krawczyk 17283adcba9aSMichal Krawczyk if (polling) 17293adcba9aSMichal Krawczyk mask_value = ENA_REGS_ADMIN_INTR_MASK; 17303adcba9aSMichal Krawczyk 1731b68309beSRafal Kozik ENA_REG_WRITE32(ena_dev->bus, mask_value, 1732b68309beSRafal Kozik ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF); 173399ecfbf8SJan Medala ena_dev->admin_queue.polling = polling; 173499ecfbf8SJan Medala } 173599ecfbf8SJan Medala 1736b2b02edeSMichal Krawczyk bool ena_com_get_admin_polling_mode(struct ena_com_dev *ena_dev) 1737b2b02edeSMichal Krawczyk { 1738b2b02edeSMichal Krawczyk return ena_dev->admin_queue.polling; 1739b2b02edeSMichal Krawczyk } 1740b2b02edeSMichal Krawczyk 1741b2b02edeSMichal Krawczyk void ena_com_set_admin_auto_polling_mode(struct ena_com_dev *ena_dev, 1742b2b02edeSMichal Krawczyk bool polling) 1743b2b02edeSMichal Krawczyk { 1744b2b02edeSMichal Krawczyk ena_dev->admin_queue.auto_polling = polling; 1745b2b02edeSMichal Krawczyk } 1746b2b02edeSMichal Krawczyk 1747f73f53f7SShai Brandes bool ena_com_phc_supported(struct ena_com_dev *ena_dev) 1748f73f53f7SShai Brandes { 1749f73f53f7SShai Brandes return ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_PHC_CONFIG); 1750f73f53f7SShai Brandes } 1751f73f53f7SShai Brandes 1752f73f53f7SShai Brandes int ena_com_phc_init(struct ena_com_dev *ena_dev) 1753f73f53f7SShai Brandes { 1754f73f53f7SShai Brandes struct ena_com_phc_info *phc = &ena_dev->phc; 1755f73f53f7SShai Brandes 1756f73f53f7SShai Brandes memset(phc, 0x0, sizeof(*phc)); 1757f73f53f7SShai Brandes 1758f73f53f7SShai Brandes /* Allocate shared mem used PHC timestamp retrieved from device */ 1759f73f53f7SShai Brandes ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 1760f73f53f7SShai Brandes sizeof(*phc->virt_addr), 1761f73f53f7SShai Brandes phc->virt_addr, 1762f73f53f7SShai Brandes phc->phys_addr, 1763f73f53f7SShai Brandes phc->mem_handle); 1764f73f53f7SShai Brandes if (unlikely(!phc->virt_addr)) 1765f73f53f7SShai Brandes return ENA_COM_NO_MEM; 1766f73f53f7SShai Brandes 1767f73f53f7SShai Brandes ENA_SPINLOCK_INIT(phc->lock); 1768f73f53f7SShai Brandes 1769f73f53f7SShai Brandes phc->virt_addr->req_id = 0; 1770f73f53f7SShai Brandes phc->virt_addr->timestamp = 0; 1771f73f53f7SShai Brandes 1772f73f53f7SShai Brandes return 0; 1773f73f53f7SShai Brandes } 1774f73f53f7SShai Brandes 1775f73f53f7SShai Brandes int ena_com_phc_config(struct ena_com_dev *ena_dev) 1776f73f53f7SShai Brandes { 1777f73f53f7SShai Brandes struct ena_com_phc_info *phc = &ena_dev->phc; 1778f73f53f7SShai Brandes struct ena_admin_get_feat_resp get_feat_resp; 1779f73f53f7SShai Brandes struct ena_admin_set_feat_resp set_feat_resp; 1780f73f53f7SShai Brandes struct ena_admin_set_feat_cmd set_feat_cmd; 1781f73f53f7SShai Brandes int ret = 0; 1782f73f53f7SShai Brandes 1783*319b51fdSShai Brandes /* Get default device PHC configuration */ 1784*319b51fdSShai Brandes ret = ena_com_get_feature(ena_dev, 1785*319b51fdSShai Brandes &get_feat_resp, 1786*319b51fdSShai Brandes ENA_ADMIN_PHC_CONFIG, 1787*319b51fdSShai Brandes ENA_ADMIN_PHC_FEATURE_VERSION_0); 1788f73f53f7SShai Brandes if (unlikely(ret)) { 1789f73f53f7SShai Brandes ena_trc_err(ena_dev, "Failed to get PHC feature configuration, error: %d\n", ret); 1790f73f53f7SShai Brandes return ret; 1791f73f53f7SShai Brandes } 1792f73f53f7SShai Brandes 1793*319b51fdSShai Brandes /* Supporting only PHC V0 (readless mode with error bound) */ 1794*319b51fdSShai Brandes if (get_feat_resp.u.phc.version != ENA_ADMIN_PHC_FEATURE_VERSION_0) { 1795*319b51fdSShai Brandes ena_trc_err(ena_dev, "Unsupported PHC version (0x%X), error: %d\n", 1796*319b51fdSShai Brandes get_feat_resp.u.phc.version, 1797*319b51fdSShai Brandes ENA_COM_UNSUPPORTED); 1798f73f53f7SShai Brandes return ENA_COM_UNSUPPORTED; 1799f73f53f7SShai Brandes } 1800f73f53f7SShai Brandes 1801f73f53f7SShai Brandes /* Update PHC doorbell offset according to device value, used to write req_id to PHC bar */ 1802f73f53f7SShai Brandes phc->doorbell_offset = get_feat_resp.u.phc.doorbell_offset; 1803f73f53f7SShai Brandes 1804f73f53f7SShai Brandes /* Update PHC expire timeout according to device or default driver value */ 1805f73f53f7SShai Brandes phc->expire_timeout_usec = (get_feat_resp.u.phc.expire_timeout_usec) ? 1806f73f53f7SShai Brandes get_feat_resp.u.phc.expire_timeout_usec : 1807f73f53f7SShai Brandes ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC; 1808f73f53f7SShai Brandes 1809f73f53f7SShai Brandes /* Update PHC block timeout according to device or default driver value */ 1810f73f53f7SShai Brandes phc->block_timeout_usec = (get_feat_resp.u.phc.block_timeout_usec) ? 1811f73f53f7SShai Brandes get_feat_resp.u.phc.block_timeout_usec : 1812f73f53f7SShai Brandes ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC; 1813f73f53f7SShai Brandes 1814*319b51fdSShai Brandes /* Sanity check - expire timeout must not exceed block timeout */ 1815f73f53f7SShai Brandes if (phc->expire_timeout_usec > phc->block_timeout_usec) 1816f73f53f7SShai Brandes phc->expire_timeout_usec = phc->block_timeout_usec; 1817f73f53f7SShai Brandes 1818*319b51fdSShai Brandes /* Prepare PHC config feature command */ 1819f73f53f7SShai Brandes memset(&set_feat_cmd, 0x0, sizeof(set_feat_cmd)); 1820f73f53f7SShai Brandes set_feat_cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 1821f73f53f7SShai Brandes set_feat_cmd.feat_common.feature_id = ENA_ADMIN_PHC_CONFIG; 1822f73f53f7SShai Brandes set_feat_cmd.u.phc.output_length = sizeof(*phc->virt_addr); 1823f73f53f7SShai Brandes ret = ena_com_mem_addr_set(ena_dev, &set_feat_cmd.u.phc.output_address, phc->phys_addr); 1824f73f53f7SShai Brandes if (unlikely(ret)) { 1825f73f53f7SShai Brandes ena_trc_err(ena_dev, "Failed setting PHC output address, error: %d\n", ret); 1826f73f53f7SShai Brandes return ret; 1827f73f53f7SShai Brandes } 1828f73f53f7SShai Brandes 1829f73f53f7SShai Brandes /* Send PHC feature command to the device */ 1830f73f53f7SShai Brandes ret = ena_com_execute_admin_command(&ena_dev->admin_queue, 1831f73f53f7SShai Brandes (struct ena_admin_aq_entry *)&set_feat_cmd, 1832f73f53f7SShai Brandes sizeof(set_feat_cmd), 1833f73f53f7SShai Brandes (struct ena_admin_acq_entry *)&set_feat_resp, 1834f73f53f7SShai Brandes sizeof(set_feat_resp)); 1835f73f53f7SShai Brandes 1836f73f53f7SShai Brandes if (unlikely(ret)) { 1837f73f53f7SShai Brandes ena_trc_err(ena_dev, "Failed to enable PHC, error: %d\n", ret); 1838f73f53f7SShai Brandes return ret; 1839f73f53f7SShai Brandes } 1840f73f53f7SShai Brandes 1841f73f53f7SShai Brandes phc->active = true; 1842f73f53f7SShai Brandes ena_trc_dbg(ena_dev, "PHC is active in the device\n"); 1843f73f53f7SShai Brandes 1844f73f53f7SShai Brandes return ret; 1845f73f53f7SShai Brandes } 1846f73f53f7SShai Brandes 1847f73f53f7SShai Brandes void ena_com_phc_destroy(struct ena_com_dev *ena_dev) 1848f73f53f7SShai Brandes { 1849f73f53f7SShai Brandes struct ena_com_phc_info *phc = &ena_dev->phc; 1850*319b51fdSShai Brandes unsigned long flags = 0; 1851f73f53f7SShai Brandes 1852f73f53f7SShai Brandes /* In case PHC is not supported by the device, silently exiting */ 1853f73f53f7SShai Brandes if (!phc->virt_addr) 1854f73f53f7SShai Brandes return; 1855f73f53f7SShai Brandes 1856*319b51fdSShai Brandes ENA_SPINLOCK_LOCK(phc->lock, flags); 1857*319b51fdSShai Brandes phc->active = false; 1858*319b51fdSShai Brandes ENA_SPINLOCK_UNLOCK(phc->lock, flags); 1859*319b51fdSShai Brandes 1860f73f53f7SShai Brandes ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 1861f73f53f7SShai Brandes sizeof(*phc->virt_addr), 1862f73f53f7SShai Brandes phc->virt_addr, 1863f73f53f7SShai Brandes phc->phys_addr, 1864f73f53f7SShai Brandes phc->mem_handle); 1865f73f53f7SShai Brandes phc->virt_addr = NULL; 1866f73f53f7SShai Brandes 1867f73f53f7SShai Brandes ENA_SPINLOCK_DESTROY(phc->lock); 1868f73f53f7SShai Brandes } 1869f73f53f7SShai Brandes 1870*319b51fdSShai Brandes int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp) 1871f73f53f7SShai Brandes { 1872f73f53f7SShai Brandes volatile struct ena_admin_phc_resp *read_resp = ena_dev->phc.virt_addr; 1873*319b51fdSShai Brandes const ena_time_high_res_t zero_system_time = ENA_TIME_INIT_HIGH_RES(); 1874f73f53f7SShai Brandes struct ena_com_phc_info *phc = &ena_dev->phc; 1875f73f53f7SShai Brandes ena_time_high_res_t expire_time; 1876f73f53f7SShai Brandes ena_time_high_res_t block_time; 1877*319b51fdSShai Brandes unsigned long flags = 0; 1878f73f53f7SShai Brandes int ret = ENA_COM_OK; 1879f73f53f7SShai Brandes 1880f73f53f7SShai Brandes if (!phc->active) { 1881f73f53f7SShai Brandes ena_trc_err(ena_dev, "PHC feature is not active in the device\n"); 1882f73f53f7SShai Brandes return ENA_COM_UNSUPPORTED; 1883f73f53f7SShai Brandes } 1884f73f53f7SShai Brandes 1885f73f53f7SShai Brandes ENA_SPINLOCK_LOCK(phc->lock, flags); 1886f73f53f7SShai Brandes 1887f73f53f7SShai Brandes /* Check if PHC is in blocked state */ 1888*319b51fdSShai Brandes if (unlikely(ENA_TIME_COMPARE_HIGH_RES(phc->system_time, zero_system_time))) { 1889f73f53f7SShai Brandes /* Check if blocking time expired */ 1890*319b51fdSShai Brandes block_time = ENA_GET_SYSTEM_TIMEOUT_HIGH_RES(phc->system_time, 1891*319b51fdSShai Brandes phc->block_timeout_usec); 1892f73f53f7SShai Brandes if (!ENA_TIME_EXPIRE_HIGH_RES(block_time)) { 1893f73f53f7SShai Brandes /* PHC is still in blocked state, skip PHC request */ 1894f73f53f7SShai Brandes phc->stats.phc_skp++; 1895f73f53f7SShai Brandes ret = ENA_COM_DEVICE_BUSY; 1896f73f53f7SShai Brandes goto skip; 1897f73f53f7SShai Brandes } 1898f73f53f7SShai Brandes 1899*319b51fdSShai Brandes /* PHC is in active state, update statistics according to req_id and error_flags */ 1900f73f53f7SShai Brandes if ((READ_ONCE16(read_resp->req_id) != phc->req_id) || 1901*319b51fdSShai Brandes (read_resp->error_flags & ENA_PHC_ERROR_FLAGS)) { 1902f73f53f7SShai Brandes /* Device didn't update req_id during blocking time or timestamp is invalid, 1903f73f53f7SShai Brandes * this indicates on a device error 1904f73f53f7SShai Brandes */ 1905f73f53f7SShai Brandes phc->stats.phc_err++; 1906*319b51fdSShai Brandes } else { 1907f73f53f7SShai Brandes /* Device updated req_id during blocking time with valid timestamp */ 1908f73f53f7SShai Brandes phc->stats.phc_exp++; 1909f73f53f7SShai Brandes } 1910*319b51fdSShai Brandes } 1911f73f53f7SShai Brandes 1912f73f53f7SShai Brandes /* Setting relative timeouts */ 1913*319b51fdSShai Brandes phc->system_time = ENA_GET_SYSTEM_TIME_HIGH_RES(); 1914*319b51fdSShai Brandes block_time = ENA_GET_SYSTEM_TIMEOUT_HIGH_RES(phc->system_time, phc->block_timeout_usec); 1915*319b51fdSShai Brandes expire_time = ENA_GET_SYSTEM_TIMEOUT_HIGH_RES(phc->system_time, phc->expire_timeout_usec); 1916f73f53f7SShai Brandes 1917f73f53f7SShai Brandes /* We expect the device to return this req_id once the new PHC timestamp is updated */ 1918f73f53f7SShai Brandes phc->req_id++; 1919f73f53f7SShai Brandes 1920f73f53f7SShai Brandes /* Initialize PHC shared memory with different req_id value to be able to identify once the 1921f73f53f7SShai Brandes * device changes it to req_id 1922f73f53f7SShai Brandes */ 1923f73f53f7SShai Brandes read_resp->req_id = phc->req_id + ENA_PHC_REQ_ID_OFFSET; 1924f73f53f7SShai Brandes 1925f73f53f7SShai Brandes /* Writing req_id to PHC bar */ 1926f73f53f7SShai Brandes ENA_REG_WRITE32(ena_dev->bus, phc->req_id, ena_dev->reg_bar + phc->doorbell_offset); 1927f73f53f7SShai Brandes 1928f73f53f7SShai Brandes /* Stalling until the device updates req_id */ 1929f73f53f7SShai Brandes while (1) { 1930f73f53f7SShai Brandes if (unlikely(ENA_TIME_EXPIRE_HIGH_RES(expire_time))) { 1931f73f53f7SShai Brandes /* Gave up waiting for updated req_id, PHC enters into blocked state until 1932*319b51fdSShai Brandes * passing blocking time, during this time any get PHC timestamp or 1933*319b51fdSShai Brandes * error bound requests will fail with device busy error 1934f73f53f7SShai Brandes */ 1935*319b51fdSShai Brandes phc->error_bound = ENA_PHC_MAX_ERROR_BOUND; 1936f73f53f7SShai Brandes ret = ENA_COM_DEVICE_BUSY; 1937f73f53f7SShai Brandes break; 1938f73f53f7SShai Brandes } 1939f73f53f7SShai Brandes 1940f73f53f7SShai Brandes /* Check if req_id was updated by the device */ 1941f73f53f7SShai Brandes if (READ_ONCE16(read_resp->req_id) != phc->req_id) { 1942*319b51fdSShai Brandes /* req_id was not updated by the device yet, check again on next loop */ 1943f73f53f7SShai Brandes continue; 1944f73f53f7SShai Brandes } 1945f73f53f7SShai Brandes 1946*319b51fdSShai Brandes /* req_id was updated by the device which indicates that PHC timestamp, error_bound 1947*319b51fdSShai Brandes * and error_flags are updated too, checking errors before retrieving timestamp and 1948*319b51fdSShai Brandes * error_bound values 1949f73f53f7SShai Brandes */ 1950*319b51fdSShai Brandes if (unlikely(read_resp->error_flags & ENA_PHC_ERROR_FLAGS)) { 1951*319b51fdSShai Brandes /* Retrieved timestamp or error bound errors, PHC enters into blocked state 1952*319b51fdSShai Brandes * until passing blocking time, during this time any get PHC timestamp or 1953*319b51fdSShai Brandes * error bound requests will fail with device busy error 1954*319b51fdSShai Brandes */ 1955*319b51fdSShai Brandes phc->error_bound = ENA_PHC_MAX_ERROR_BOUND; 1956f73f53f7SShai Brandes ret = ENA_COM_DEVICE_BUSY; 1957f73f53f7SShai Brandes break; 1958f73f53f7SShai Brandes } 1959f73f53f7SShai Brandes 1960*319b51fdSShai Brandes /* PHC timestamp value is returned to the caller */ 1961*319b51fdSShai Brandes *timestamp = read_resp->timestamp; 1962*319b51fdSShai Brandes 1963*319b51fdSShai Brandes /* Error bound value is cached for future retrieval by caller */ 1964*319b51fdSShai Brandes phc->error_bound = read_resp->error_bound; 1965*319b51fdSShai Brandes 1966*319b51fdSShai Brandes /* Update statistic on valid PHC timestamp retrieval */ 1967f73f53f7SShai Brandes phc->stats.phc_cnt++; 1968f73f53f7SShai Brandes 1969f73f53f7SShai Brandes /* This indicates PHC state is active */ 1970*319b51fdSShai Brandes phc->system_time = zero_system_time; 1971f73f53f7SShai Brandes break; 1972f73f53f7SShai Brandes } 1973f73f53f7SShai Brandes 1974f73f53f7SShai Brandes skip: 1975f73f53f7SShai Brandes ENA_SPINLOCK_UNLOCK(phc->lock, flags); 1976f73f53f7SShai Brandes 1977f73f53f7SShai Brandes return ret; 1978f73f53f7SShai Brandes } 1979f73f53f7SShai Brandes 1980*319b51fdSShai Brandes int ena_com_phc_get_error_bound(struct ena_com_dev *ena_dev, u32 *error_bound) 1981*319b51fdSShai Brandes { 1982*319b51fdSShai Brandes struct ena_com_phc_info *phc = &ena_dev->phc; 1983*319b51fdSShai Brandes u32 local_error_bound = phc->error_bound; 1984*319b51fdSShai Brandes 1985*319b51fdSShai Brandes if (!phc->active) { 1986*319b51fdSShai Brandes ena_trc_err(ena_dev, "PHC feature is not active in the device\n"); 1987*319b51fdSShai Brandes return ENA_COM_UNSUPPORTED; 1988*319b51fdSShai Brandes } 1989*319b51fdSShai Brandes 1990*319b51fdSShai Brandes if (local_error_bound == ENA_PHC_MAX_ERROR_BOUND) 1991*319b51fdSShai Brandes return ENA_COM_DEVICE_BUSY; 1992*319b51fdSShai Brandes 1993*319b51fdSShai Brandes *error_bound = local_error_bound; 1994*319b51fdSShai Brandes 1995*319b51fdSShai Brandes return ENA_COM_OK; 1996*319b51fdSShai Brandes } 1997*319b51fdSShai Brandes 199899ecfbf8SJan Medala int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev) 199999ecfbf8SJan Medala { 200099ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 200199ecfbf8SJan Medala 200299ecfbf8SJan Medala ENA_SPINLOCK_INIT(mmio_read->lock); 200399ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 200499ecfbf8SJan Medala sizeof(*mmio_read->read_resp), 200599ecfbf8SJan Medala mmio_read->read_resp, 200699ecfbf8SJan Medala mmio_read->read_resp_dma_addr, 200799ecfbf8SJan Medala mmio_read->read_resp_mem_handle); 200899ecfbf8SJan Medala if (unlikely(!mmio_read->read_resp)) 2009b68309beSRafal Kozik goto err; 201099ecfbf8SJan Medala 201199ecfbf8SJan Medala ena_com_mmio_reg_read_request_write_dev_addr(ena_dev); 201299ecfbf8SJan Medala 201399ecfbf8SJan Medala mmio_read->read_resp->req_id = 0x0; 201499ecfbf8SJan Medala mmio_read->seq_num = 0x0; 201599ecfbf8SJan Medala mmio_read->readless_supported = true; 201699ecfbf8SJan Medala 201799ecfbf8SJan Medala return 0; 2018b68309beSRafal Kozik 2019b68309beSRafal Kozik err: 2020b68309beSRafal Kozik ENA_SPINLOCK_DESTROY(mmio_read->lock); 2021b68309beSRafal Kozik return ENA_COM_NO_MEM; 202299ecfbf8SJan Medala } 202399ecfbf8SJan Medala 20243adcba9aSMichal Krawczyk void ena_com_set_mmio_read_mode(struct ena_com_dev *ena_dev, bool readless_supported) 202599ecfbf8SJan Medala { 202699ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 202799ecfbf8SJan Medala 202899ecfbf8SJan Medala mmio_read->readless_supported = readless_supported; 202999ecfbf8SJan Medala } 203099ecfbf8SJan Medala 203199ecfbf8SJan Medala void ena_com_mmio_reg_read_request_destroy(struct ena_com_dev *ena_dev) 203299ecfbf8SJan Medala { 203399ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 203499ecfbf8SJan Medala 20353adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, 0x0, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_LO_OFF); 20363adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, 0x0, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_HI_OFF); 203799ecfbf8SJan Medala 203899ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 203999ecfbf8SJan Medala sizeof(*mmio_read->read_resp), 204099ecfbf8SJan Medala mmio_read->read_resp, 204199ecfbf8SJan Medala mmio_read->read_resp_dma_addr, 204299ecfbf8SJan Medala mmio_read->read_resp_mem_handle); 204399ecfbf8SJan Medala 204499ecfbf8SJan Medala mmio_read->read_resp = NULL; 2045b68309beSRafal Kozik ENA_SPINLOCK_DESTROY(mmio_read->lock); 204699ecfbf8SJan Medala } 204799ecfbf8SJan Medala 204899ecfbf8SJan Medala void ena_com_mmio_reg_read_request_write_dev_addr(struct ena_com_dev *ena_dev) 204999ecfbf8SJan Medala { 205099ecfbf8SJan Medala struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; 205199ecfbf8SJan Medala u32 addr_low, addr_high; 205299ecfbf8SJan Medala 205399ecfbf8SJan Medala addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(mmio_read->read_resp_dma_addr); 205499ecfbf8SJan Medala addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(mmio_read->read_resp_dma_addr); 205599ecfbf8SJan Medala 20563adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_LO_OFF); 20573adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_MMIO_RESP_HI_OFF); 205899ecfbf8SJan Medala } 205999ecfbf8SJan Medala 206099ecfbf8SJan Medala int ena_com_admin_init(struct ena_com_dev *ena_dev, 2061b68309beSRafal Kozik struct ena_aenq_handlers *aenq_handlers) 206299ecfbf8SJan Medala { 206399ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 206499ecfbf8SJan Medala u32 aq_caps, acq_caps, dev_sts, addr_low, addr_high; 206599ecfbf8SJan Medala int ret; 206699ecfbf8SJan Medala 206799ecfbf8SJan Medala dev_sts = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF); 206899ecfbf8SJan Medala 206999ecfbf8SJan Medala if (unlikely(dev_sts == ENA_MMIO_READ_TIMEOUT)) { 2070ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reg read timeout occurred\n"); 207199ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 207299ecfbf8SJan Medala } 207399ecfbf8SJan Medala 207499ecfbf8SJan Medala if (!(dev_sts & ENA_REGS_DEV_STS_READY_MASK)) { 2075ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Device isn't ready, abort com init\n"); 20766dcee7cdSJan Medala return ENA_COM_NO_DEVICE; 207799ecfbf8SJan Medala } 207899ecfbf8SJan Medala 207999ecfbf8SJan Medala admin_queue->q_depth = ENA_ADMIN_QUEUE_DEPTH; 208099ecfbf8SJan Medala 2081b68309beSRafal Kozik admin_queue->bus = ena_dev->bus; 208299ecfbf8SJan Medala admin_queue->q_dmadev = ena_dev->dmadev; 208399ecfbf8SJan Medala admin_queue->polling = false; 208499ecfbf8SJan Medala admin_queue->curr_cmd_id = 0; 208599ecfbf8SJan Medala 208699ecfbf8SJan Medala ATOMIC32_SET(&admin_queue->outstanding_cmds, 0); 208799ecfbf8SJan Medala 208899ecfbf8SJan Medala ENA_SPINLOCK_INIT(admin_queue->q_lock); 208999ecfbf8SJan Medala 209099ecfbf8SJan Medala ret = ena_com_init_comp_ctxt(admin_queue); 209199ecfbf8SJan Medala if (ret) 209299ecfbf8SJan Medala goto error; 209399ecfbf8SJan Medala 209499ecfbf8SJan Medala ret = ena_com_admin_init_sq(admin_queue); 209599ecfbf8SJan Medala if (ret) 209699ecfbf8SJan Medala goto error; 209799ecfbf8SJan Medala 209899ecfbf8SJan Medala ret = ena_com_admin_init_cq(admin_queue); 209999ecfbf8SJan Medala if (ret) 210099ecfbf8SJan Medala goto error; 210199ecfbf8SJan Medala 21023adcba9aSMichal Krawczyk admin_queue->sq.db_addr = (u32 __iomem *)((uintptr_t)ena_dev->reg_bar + 21033adcba9aSMichal Krawczyk ENA_REGS_AQ_DB_OFF); 210499ecfbf8SJan Medala 210599ecfbf8SJan Medala addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(admin_queue->sq.dma_addr); 210699ecfbf8SJan Medala addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(admin_queue->sq.dma_addr); 210799ecfbf8SJan Medala 21083adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_AQ_BASE_LO_OFF); 21093adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_AQ_BASE_HI_OFF); 211099ecfbf8SJan Medala 211199ecfbf8SJan Medala addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(admin_queue->cq.dma_addr); 211299ecfbf8SJan Medala addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(admin_queue->cq.dma_addr); 211399ecfbf8SJan Medala 21143adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_low, ena_dev->reg_bar + ENA_REGS_ACQ_BASE_LO_OFF); 21153adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, addr_high, ena_dev->reg_bar + ENA_REGS_ACQ_BASE_HI_OFF); 211699ecfbf8SJan Medala 211799ecfbf8SJan Medala aq_caps = 0; 211899ecfbf8SJan Medala aq_caps |= admin_queue->q_depth & ENA_REGS_AQ_CAPS_AQ_DEPTH_MASK; 211999ecfbf8SJan Medala aq_caps |= (sizeof(struct ena_admin_aq_entry) << 212099ecfbf8SJan Medala ENA_REGS_AQ_CAPS_AQ_ENTRY_SIZE_SHIFT) & 212199ecfbf8SJan Medala ENA_REGS_AQ_CAPS_AQ_ENTRY_SIZE_MASK; 212299ecfbf8SJan Medala 212399ecfbf8SJan Medala acq_caps = 0; 212499ecfbf8SJan Medala acq_caps |= admin_queue->q_depth & ENA_REGS_ACQ_CAPS_ACQ_DEPTH_MASK; 212599ecfbf8SJan Medala acq_caps |= (sizeof(struct ena_admin_acq_entry) << 212699ecfbf8SJan Medala ENA_REGS_ACQ_CAPS_ACQ_ENTRY_SIZE_SHIFT) & 212799ecfbf8SJan Medala ENA_REGS_ACQ_CAPS_ACQ_ENTRY_SIZE_MASK; 212899ecfbf8SJan Medala 21293adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, aq_caps, ena_dev->reg_bar + ENA_REGS_AQ_CAPS_OFF); 21303adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, acq_caps, ena_dev->reg_bar + ENA_REGS_ACQ_CAPS_OFF); 213199ecfbf8SJan Medala ret = ena_com_admin_init_aenq(ena_dev, aenq_handlers); 213299ecfbf8SJan Medala if (ret) 213399ecfbf8SJan Medala goto error; 213499ecfbf8SJan Medala 21350c84e048SMichal Krawczyk admin_queue->ena_dev = ena_dev; 213699ecfbf8SJan Medala admin_queue->running_state = true; 213799ecfbf8SJan Medala 213899ecfbf8SJan Medala return 0; 213999ecfbf8SJan Medala error: 214099ecfbf8SJan Medala ena_com_admin_destroy(ena_dev); 214199ecfbf8SJan Medala 214299ecfbf8SJan Medala return ret; 214399ecfbf8SJan Medala } 214499ecfbf8SJan Medala 214599ecfbf8SJan Medala int ena_com_create_io_queue(struct ena_com_dev *ena_dev, 21466dcee7cdSJan Medala struct ena_com_create_io_ctx *ctx) 214799ecfbf8SJan Medala { 214899ecfbf8SJan Medala struct ena_com_io_sq *io_sq; 214999ecfbf8SJan Medala struct ena_com_io_cq *io_cq; 21503adcba9aSMichal Krawczyk int ret; 215199ecfbf8SJan Medala 21526dcee7cdSJan Medala if (ctx->qid >= ENA_TOTAL_NUM_QUEUES) { 2153ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Qid (%d) is bigger than max num of queues (%d)\n", 21546dcee7cdSJan Medala ctx->qid, ENA_TOTAL_NUM_QUEUES); 215599ecfbf8SJan Medala return ENA_COM_INVAL; 215699ecfbf8SJan Medala } 215799ecfbf8SJan Medala 21586dcee7cdSJan Medala io_sq = &ena_dev->io_sq_queues[ctx->qid]; 21596dcee7cdSJan Medala io_cq = &ena_dev->io_cq_queues[ctx->qid]; 216099ecfbf8SJan Medala 21613adcba9aSMichal Krawczyk memset(io_sq, 0x0, sizeof(*io_sq)); 21623adcba9aSMichal Krawczyk memset(io_cq, 0x0, sizeof(*io_cq)); 216399ecfbf8SJan Medala 216499ecfbf8SJan Medala /* Init CQ */ 21656dcee7cdSJan Medala io_cq->q_depth = ctx->queue_size; 21666dcee7cdSJan Medala io_cq->direction = ctx->direction; 21676dcee7cdSJan Medala io_cq->qid = ctx->qid; 216899ecfbf8SJan Medala 21696dcee7cdSJan Medala io_cq->msix_vector = ctx->msix_vector; 217099ecfbf8SJan Medala 21716dcee7cdSJan Medala io_sq->q_depth = ctx->queue_size; 21726dcee7cdSJan Medala io_sq->direction = ctx->direction; 21736dcee7cdSJan Medala io_sq->qid = ctx->qid; 217499ecfbf8SJan Medala 21756dcee7cdSJan Medala io_sq->mem_queue_type = ctx->mem_queue_type; 217699ecfbf8SJan Medala 21776dcee7cdSJan Medala if (ctx->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) 217899ecfbf8SJan Medala /* header length is limited to 8 bits */ 217999ecfbf8SJan Medala io_sq->tx_max_header_size = 21806dcee7cdSJan Medala ENA_MIN32(ena_dev->tx_max_header_size, SZ_256); 218199ecfbf8SJan Medala 21826dcee7cdSJan Medala ret = ena_com_init_io_sq(ena_dev, ctx, io_sq); 218399ecfbf8SJan Medala if (ret) 218499ecfbf8SJan Medala goto error; 21856dcee7cdSJan Medala ret = ena_com_init_io_cq(ena_dev, ctx, io_cq); 218699ecfbf8SJan Medala if (ret) 218799ecfbf8SJan Medala goto error; 218899ecfbf8SJan Medala 218999ecfbf8SJan Medala ret = ena_com_create_io_cq(ena_dev, io_cq); 219099ecfbf8SJan Medala if (ret) 219199ecfbf8SJan Medala goto error; 219299ecfbf8SJan Medala 219399ecfbf8SJan Medala ret = ena_com_create_io_sq(ena_dev, io_sq, io_cq->idx); 219499ecfbf8SJan Medala if (ret) 219599ecfbf8SJan Medala goto destroy_io_cq; 219699ecfbf8SJan Medala 219799ecfbf8SJan Medala return 0; 219899ecfbf8SJan Medala 219999ecfbf8SJan Medala destroy_io_cq: 220099ecfbf8SJan Medala ena_com_destroy_io_cq(ena_dev, io_cq); 220199ecfbf8SJan Medala error: 220299ecfbf8SJan Medala ena_com_io_queue_free(ena_dev, io_sq, io_cq); 220399ecfbf8SJan Medala return ret; 220499ecfbf8SJan Medala } 220599ecfbf8SJan Medala 220699ecfbf8SJan Medala void ena_com_destroy_io_queue(struct ena_com_dev *ena_dev, u16 qid) 220799ecfbf8SJan Medala { 220899ecfbf8SJan Medala struct ena_com_io_sq *io_sq; 220999ecfbf8SJan Medala struct ena_com_io_cq *io_cq; 221099ecfbf8SJan Medala 221199ecfbf8SJan Medala if (qid >= ENA_TOTAL_NUM_QUEUES) { 2212ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Qid (%d) is bigger than max num of queues (%d)\n", 221399ecfbf8SJan Medala qid, ENA_TOTAL_NUM_QUEUES); 221499ecfbf8SJan Medala return; 221599ecfbf8SJan Medala } 221699ecfbf8SJan Medala 221799ecfbf8SJan Medala io_sq = &ena_dev->io_sq_queues[qid]; 221899ecfbf8SJan Medala io_cq = &ena_dev->io_cq_queues[qid]; 221999ecfbf8SJan Medala 222099ecfbf8SJan Medala ena_com_destroy_io_sq(ena_dev, io_sq); 222199ecfbf8SJan Medala ena_com_destroy_io_cq(ena_dev, io_cq); 222299ecfbf8SJan Medala 222399ecfbf8SJan Medala ena_com_io_queue_free(ena_dev, io_sq, io_cq); 222499ecfbf8SJan Medala } 222599ecfbf8SJan Medala 222699ecfbf8SJan Medala int ena_com_get_link_params(struct ena_com_dev *ena_dev, 222799ecfbf8SJan Medala struct ena_admin_get_feat_resp *resp) 222899ecfbf8SJan Medala { 2229b68309beSRafal Kozik return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG, 0); 2230b68309beSRafal Kozik } 2231b68309beSRafal Kozik 2232f73f53f7SShai Brandes static int ena_get_dev_stats(struct ena_com_dev *ena_dev, 2233f73f53f7SShai Brandes struct ena_com_stats_ctx *ctx, 2234f73f53f7SShai Brandes enum ena_admin_get_stats_type type) 2235f73f53f7SShai Brandes { 2236f73f53f7SShai Brandes struct ena_admin_acq_get_stats_resp *get_resp = &ctx->get_resp; 2237f73f53f7SShai Brandes struct ena_admin_aq_get_stats_cmd *get_cmd = &ctx->get_cmd; 2238f73f53f7SShai Brandes struct ena_com_admin_queue *admin_queue; 2239f73f53f7SShai Brandes int ret; 2240f73f53f7SShai Brandes 2241f73f53f7SShai Brandes admin_queue = &ena_dev->admin_queue; 2242f73f53f7SShai Brandes 2243f73f53f7SShai Brandes get_cmd->aq_common_descriptor.opcode = ENA_ADMIN_GET_STATS; 2244f73f53f7SShai Brandes get_cmd->aq_common_descriptor.flags = 0; 2245f73f53f7SShai Brandes get_cmd->type = type; 2246f73f53f7SShai Brandes 2247f73f53f7SShai Brandes ret = ena_com_execute_admin_command(admin_queue, 2248f73f53f7SShai Brandes (struct ena_admin_aq_entry *)get_cmd, 2249f73f53f7SShai Brandes sizeof(*get_cmd), 2250f73f53f7SShai Brandes (struct ena_admin_acq_entry *)get_resp, 2251f73f53f7SShai Brandes sizeof(*get_resp)); 2252f73f53f7SShai Brandes 2253f73f53f7SShai Brandes if (unlikely(ret)) 2254f73f53f7SShai Brandes ena_trc_err(ena_dev, "Failed to get stats. error: %d\n", ret); 2255f73f53f7SShai Brandes 2256f73f53f7SShai Brandes return ret; 2257f73f53f7SShai Brandes } 2258f73f53f7SShai Brandes 2259f73f53f7SShai Brandes static void ena_com_set_supported_customer_metrics(struct ena_com_dev *ena_dev) 2260f73f53f7SShai Brandes { 2261f73f53f7SShai Brandes struct ena_customer_metrics *customer_metrics; 2262f73f53f7SShai Brandes struct ena_com_stats_ctx ctx; 2263f73f53f7SShai Brandes int ret; 2264f73f53f7SShai Brandes 2265f73f53f7SShai Brandes customer_metrics = &ena_dev->customer_metrics; 2266f73f53f7SShai Brandes if (!ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) { 2267f73f53f7SShai Brandes customer_metrics->supported_metrics = ENA_ADMIN_CUSTOMER_METRICS_MIN_SUPPORT_MASK; 2268f73f53f7SShai Brandes return; 2269f73f53f7SShai Brandes } 2270f73f53f7SShai Brandes 2271f73f53f7SShai Brandes memset(&ctx, 0x0, sizeof(ctx)); 2272f73f53f7SShai Brandes ctx.get_cmd.requested_metrics = ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK; 2273f73f53f7SShai Brandes ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS); 2274f73f53f7SShai Brandes if (likely(ret == 0)) 2275f73f53f7SShai Brandes customer_metrics->supported_metrics = 2276f73f53f7SShai Brandes ctx.get_resp.u.customer_metrics.reported_metrics; 2277f73f53f7SShai Brandes else 2278f73f53f7SShai Brandes ena_trc_err(ena_dev, "Failed to query customer metrics support. error: %d\n", ret); 2279f73f53f7SShai Brandes } 2280f73f53f7SShai Brandes 228199ecfbf8SJan Medala int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev, 228299ecfbf8SJan Medala struct ena_com_dev_get_features_ctx *get_feat_ctx) 228399ecfbf8SJan Medala { 228499ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 228599ecfbf8SJan Medala int rc; 228699ecfbf8SJan Medala 228799ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 2288b68309beSRafal Kozik ENA_ADMIN_DEVICE_ATTRIBUTES, 0); 228999ecfbf8SJan Medala if (rc) 229099ecfbf8SJan Medala return rc; 229199ecfbf8SJan Medala 229299ecfbf8SJan Medala memcpy(&get_feat_ctx->dev_attr, &get_resp.u.dev_attr, 229399ecfbf8SJan Medala sizeof(get_resp.u.dev_attr)); 2294b19f366cSMichal Krawczyk 229599ecfbf8SJan Medala ena_dev->supported_features = get_resp.u.dev_attr.supported_features; 2296f73f53f7SShai Brandes ena_dev->capabilities = get_resp.u.dev_attr.capabilities; 229799ecfbf8SJan Medala 2298b68309beSRafal Kozik if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) { 229999ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 2300b68309beSRafal Kozik ENA_ADMIN_MAX_QUEUES_EXT, 2301b68309beSRafal Kozik ENA_FEATURE_MAX_QUEUE_EXT_VER); 230299ecfbf8SJan Medala if (rc) 230399ecfbf8SJan Medala return rc; 230499ecfbf8SJan Medala 2305b68309beSRafal Kozik if (get_resp.u.max_queue_ext.version != ENA_FEATURE_MAX_QUEUE_EXT_VER) 2306f73f53f7SShai Brandes return ENA_COM_INVAL; 2307b68309beSRafal Kozik 2308b68309beSRafal Kozik memcpy(&get_feat_ctx->max_queue_ext, &get_resp.u.max_queue_ext, 2309b68309beSRafal Kozik sizeof(get_resp.u.max_queue_ext)); 2310b68309beSRafal Kozik ena_dev->tx_max_header_size = 2311b68309beSRafal Kozik get_resp.u.max_queue_ext.max_queue_ext.max_tx_header_size; 2312b68309beSRafal Kozik } else { 2313b68309beSRafal Kozik rc = ena_com_get_feature(ena_dev, &get_resp, 2314b68309beSRafal Kozik ENA_ADMIN_MAX_QUEUES_NUM, 0); 231599ecfbf8SJan Medala memcpy(&get_feat_ctx->max_queues, &get_resp.u.max_queue, 231699ecfbf8SJan Medala sizeof(get_resp.u.max_queue)); 2317b68309beSRafal Kozik ena_dev->tx_max_header_size = 2318b68309beSRafal Kozik get_resp.u.max_queue.max_header_size; 2319b68309beSRafal Kozik 2320b68309beSRafal Kozik if (rc) 2321b68309beSRafal Kozik return rc; 2322b68309beSRafal Kozik } 232399ecfbf8SJan Medala 232499ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 2325b68309beSRafal Kozik ENA_ADMIN_AENQ_CONFIG, 0); 232699ecfbf8SJan Medala if (rc) 232799ecfbf8SJan Medala return rc; 232899ecfbf8SJan Medala 232999ecfbf8SJan Medala memcpy(&get_feat_ctx->aenq, &get_resp.u.aenq, 233099ecfbf8SJan Medala sizeof(get_resp.u.aenq)); 233199ecfbf8SJan Medala 233299ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 2333b68309beSRafal Kozik ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0); 233499ecfbf8SJan Medala if (rc) 233599ecfbf8SJan Medala return rc; 233699ecfbf8SJan Medala 233799ecfbf8SJan Medala memcpy(&get_feat_ctx->offload, &get_resp.u.offload, 233899ecfbf8SJan Medala sizeof(get_resp.u.offload)); 233999ecfbf8SJan Medala 23403adcba9aSMichal Krawczyk /* Driver hints isn't mandatory admin command. So in case the 23413adcba9aSMichal Krawczyk * command isn't supported set driver hints to 0 23423adcba9aSMichal Krawczyk */ 2343b68309beSRafal Kozik rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_HW_HINTS, 0); 23443adcba9aSMichal Krawczyk 23453adcba9aSMichal Krawczyk if (!rc) 23463adcba9aSMichal Krawczyk memcpy(&get_feat_ctx->hw_hints, &get_resp.u.hw_hints, 23473adcba9aSMichal Krawczyk sizeof(get_resp.u.hw_hints)); 23483adcba9aSMichal Krawczyk else if (rc == ENA_COM_UNSUPPORTED) 23493adcba9aSMichal Krawczyk memset(&get_feat_ctx->hw_hints, 0x0, sizeof(get_feat_ctx->hw_hints)); 23503adcba9aSMichal Krawczyk else 23513adcba9aSMichal Krawczyk return rc; 23523adcba9aSMichal Krawczyk 2353f73f53f7SShai Brandes rc = ena_com_get_feature(ena_dev, &get_resp, 2354f73f53f7SShai Brandes ENA_ADMIN_LLQ, ENA_ADMIN_LLQ_FEATURE_VERSION_1); 2355b68309beSRafal Kozik if (!rc) 2356b68309beSRafal Kozik memcpy(&get_feat_ctx->llq, &get_resp.u.llq, 2357b68309beSRafal Kozik sizeof(get_resp.u.llq)); 2358b68309beSRafal Kozik else if (rc == ENA_COM_UNSUPPORTED) 2359b68309beSRafal Kozik memset(&get_feat_ctx->llq, 0x0, sizeof(get_feat_ctx->llq)); 2360b68309beSRafal Kozik else 2361b68309beSRafal Kozik return rc; 2362b68309beSRafal Kozik 2363f73f53f7SShai Brandes ena_com_set_supported_customer_metrics(ena_dev); 2364f73f53f7SShai Brandes 236599ecfbf8SJan Medala return 0; 236699ecfbf8SJan Medala } 236799ecfbf8SJan Medala 236899ecfbf8SJan Medala void ena_com_admin_q_comp_intr_handler(struct ena_com_dev *ena_dev) 236999ecfbf8SJan Medala { 237099ecfbf8SJan Medala ena_com_handle_admin_completion(&ena_dev->admin_queue); 237199ecfbf8SJan Medala } 237299ecfbf8SJan Medala 237399ecfbf8SJan Medala /* ena_handle_specific_aenq_event: 237499ecfbf8SJan Medala * return the handler that is relevant to the specific event group 237599ecfbf8SJan Medala */ 2376b4f8decdSMichal Krawczyk static ena_aenq_handler ena_com_get_specific_aenq_cb(struct ena_com_dev *ena_dev, 237799ecfbf8SJan Medala u16 group) 237899ecfbf8SJan Medala { 2379b4f8decdSMichal Krawczyk struct ena_aenq_handlers *aenq_handlers = ena_dev->aenq.aenq_handlers; 238099ecfbf8SJan Medala 238199ecfbf8SJan Medala if ((group < ENA_MAX_HANDLERS) && aenq_handlers->handlers[group]) 238299ecfbf8SJan Medala return aenq_handlers->handlers[group]; 238399ecfbf8SJan Medala 238499ecfbf8SJan Medala return aenq_handlers->unimplemented_handler; 238599ecfbf8SJan Medala } 238699ecfbf8SJan Medala 238799ecfbf8SJan Medala /* ena_aenq_intr_handler: 238899ecfbf8SJan Medala * handles the aenq incoming events. 238999ecfbf8SJan Medala * pop events from the queue and apply the specific handler 239099ecfbf8SJan Medala */ 2391b4f8decdSMichal Krawczyk void ena_com_aenq_intr_handler(struct ena_com_dev *ena_dev, void *data) 239299ecfbf8SJan Medala { 239399ecfbf8SJan Medala struct ena_admin_aenq_entry *aenq_e; 239499ecfbf8SJan Medala struct ena_admin_aenq_common_desc *aenq_common; 2395b4f8decdSMichal Krawczyk struct ena_com_aenq *aenq = &ena_dev->aenq; 2396b2b02edeSMichal Krawczyk u64 timestamp; 2397b68309beSRafal Kozik ena_aenq_handler handler_cb; 239899ecfbf8SJan Medala u16 masked_head, processed = 0; 239999ecfbf8SJan Medala u8 phase; 240099ecfbf8SJan Medala 240199ecfbf8SJan Medala masked_head = aenq->head & (aenq->q_depth - 1); 240299ecfbf8SJan Medala phase = aenq->phase; 240399ecfbf8SJan Medala aenq_e = &aenq->entries[masked_head]; /* Get first entry */ 240499ecfbf8SJan Medala aenq_common = &aenq_e->aenq_common_desc; 240599ecfbf8SJan Medala 240699ecfbf8SJan Medala /* Go over all the events */ 2407b68309beSRafal Kozik while ((READ_ONCE8(aenq_common->flags) & 2408b68309beSRafal Kozik ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK) == phase) { 2409b68309beSRafal Kozik /* Make sure the phase bit (ownership) is as expected before 2410b68309beSRafal Kozik * reading the rest of the descriptor. 2411b68309beSRafal Kozik */ 2412b68309beSRafal Kozik dma_rmb(); 2413b68309beSRafal Kozik 2414b2b02edeSMichal Krawczyk timestamp = (u64)aenq_common->timestamp_low | 2415b2b02edeSMichal Krawczyk ((u64)aenq_common->timestamp_high << 32); 2416f73f53f7SShai Brandes 2417f73f53f7SShai Brandes ena_trc_dbg(ena_dev, "AENQ! Group[%x] Syndrome[%x] timestamp: [%" ENA_PRIU64 "s]\n", 241899ecfbf8SJan Medala aenq_common->group, 2419b19f366cSMichal Krawczyk aenq_common->syndrome, 24203adcba9aSMichal Krawczyk timestamp); 242199ecfbf8SJan Medala 242299ecfbf8SJan Medala /* Handle specific event*/ 2423b4f8decdSMichal Krawczyk handler_cb = ena_com_get_specific_aenq_cb(ena_dev, 242499ecfbf8SJan Medala aenq_common->group); 242599ecfbf8SJan Medala handler_cb(data, aenq_e); /* call the actual event handler*/ 242699ecfbf8SJan Medala 242799ecfbf8SJan Medala /* Get next event entry */ 242899ecfbf8SJan Medala masked_head++; 242999ecfbf8SJan Medala processed++; 243099ecfbf8SJan Medala 243199ecfbf8SJan Medala if (unlikely(masked_head == aenq->q_depth)) { 243299ecfbf8SJan Medala masked_head = 0; 243399ecfbf8SJan Medala phase = !phase; 243499ecfbf8SJan Medala } 243599ecfbf8SJan Medala aenq_e = &aenq->entries[masked_head]; 243699ecfbf8SJan Medala aenq_common = &aenq_e->aenq_common_desc; 243799ecfbf8SJan Medala } 243899ecfbf8SJan Medala 243999ecfbf8SJan Medala aenq->head += processed; 244099ecfbf8SJan Medala aenq->phase = phase; 244199ecfbf8SJan Medala 244299ecfbf8SJan Medala /* Don't update aenq doorbell if there weren't any processed events */ 244399ecfbf8SJan Medala if (!processed) 244499ecfbf8SJan Medala return; 244599ecfbf8SJan Medala 244699ecfbf8SJan Medala /* write the aenq doorbell after all AENQ descriptors were read */ 244799ecfbf8SJan Medala mb(); 2448b4f8decdSMichal Krawczyk ENA_REG_WRITE32_RELAXED(ena_dev->bus, (u32)aenq->head, 2449b4f8decdSMichal Krawczyk ena_dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF); 2450b68309beSRafal Kozik mmiowb(); 245199ecfbf8SJan Medala } 245299ecfbf8SJan Medala 24533adcba9aSMichal Krawczyk int ena_com_dev_reset(struct ena_com_dev *ena_dev, 24543adcba9aSMichal Krawczyk enum ena_regs_reset_reason_types reset_reason) 245599ecfbf8SJan Medala { 2456f73f53f7SShai Brandes u32 reset_reason_msb, reset_reason_lsb; 245799ecfbf8SJan Medala u32 stat, timeout, cap, reset_val; 245899ecfbf8SJan Medala int rc; 245999ecfbf8SJan Medala 246099ecfbf8SJan Medala stat = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF); 246199ecfbf8SJan Medala cap = ena_com_reg_bar_read32(ena_dev, ENA_REGS_CAPS_OFF); 246299ecfbf8SJan Medala 246399ecfbf8SJan Medala if (unlikely((stat == ENA_MMIO_READ_TIMEOUT) || 246499ecfbf8SJan Medala (cap == ENA_MMIO_READ_TIMEOUT))) { 2465ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reg read32 timeout occurred\n"); 246699ecfbf8SJan Medala return ENA_COM_TIMER_EXPIRED; 246799ecfbf8SJan Medala } 246899ecfbf8SJan Medala 246999ecfbf8SJan Medala if ((stat & ENA_REGS_DEV_STS_READY_MASK) == 0) { 2470ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Device isn't ready, can't reset device\n"); 247199ecfbf8SJan Medala return ENA_COM_INVAL; 247299ecfbf8SJan Medala } 247399ecfbf8SJan Medala 247499ecfbf8SJan Medala timeout = (cap & ENA_REGS_CAPS_RESET_TIMEOUT_MASK) >> 247599ecfbf8SJan Medala ENA_REGS_CAPS_RESET_TIMEOUT_SHIFT; 247699ecfbf8SJan Medala if (timeout == 0) { 2477ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid timeout value\n"); 247899ecfbf8SJan Medala return ENA_COM_INVAL; 247999ecfbf8SJan Medala } 248099ecfbf8SJan Medala 248199ecfbf8SJan Medala /* start reset */ 248299ecfbf8SJan Medala reset_val = ENA_REGS_DEV_CTL_DEV_RESET_MASK; 2483f73f53f7SShai Brandes 2484f73f53f7SShai Brandes /* For backward compatibility, device will interpret 2485f73f53f7SShai Brandes * bits 24-27 as MSB, bits 28-31 as LSB 2486f73f53f7SShai Brandes */ 2487f73f53f7SShai Brandes reset_reason_lsb = ENA_FIELD_GET(reset_reason, ENA_RESET_REASON_LSB_MASK, 2488f73f53f7SShai Brandes ENA_RESET_REASON_LSB_OFFSET); 2489f73f53f7SShai Brandes 2490f73f53f7SShai Brandes reset_reason_msb = ENA_FIELD_GET(reset_reason, ENA_RESET_REASON_MSB_MASK, 2491f73f53f7SShai Brandes ENA_RESET_REASON_MSB_OFFSET); 2492f73f53f7SShai Brandes 2493f73f53f7SShai Brandes reset_val |= reset_reason_lsb << ENA_REGS_DEV_CTL_RESET_REASON_SHIFT; 2494f73f53f7SShai Brandes 2495*319b51fdSShai Brandes if (ena_com_get_cap(ena_dev, ENA_ADMIN_EXTENDED_RESET_REASONS)) 2496f73f53f7SShai Brandes reset_val |= reset_reason_msb << ENA_REGS_DEV_CTL_RESET_REASON_EXT_SHIFT; 2497*319b51fdSShai Brandes else if (reset_reason_msb) { 2498f73f53f7SShai Brandes /* In case the device does not support intended 2499f73f53f7SShai Brandes * extended reset reason fallback to generic 2500f73f53f7SShai Brandes */ 2501f73f53f7SShai Brandes reset_val = ENA_REGS_DEV_CTL_DEV_RESET_MASK; 2502f73f53f7SShai Brandes reset_val |= (ENA_REGS_RESET_GENERIC << ENA_REGS_DEV_CTL_RESET_REASON_SHIFT) & 25033adcba9aSMichal Krawczyk ENA_REGS_DEV_CTL_RESET_REASON_MASK; 2504f73f53f7SShai Brandes } 25053adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, reset_val, ena_dev->reg_bar + ENA_REGS_DEV_CTL_OFF); 250699ecfbf8SJan Medala 250799ecfbf8SJan Medala /* Write again the MMIO read request address */ 250899ecfbf8SJan Medala ena_com_mmio_reg_read_request_write_dev_addr(ena_dev); 250999ecfbf8SJan Medala 251099ecfbf8SJan Medala rc = wait_for_reset_state(ena_dev, timeout, 251199ecfbf8SJan Medala ENA_REGS_DEV_STS_RESET_IN_PROGRESS_MASK); 251299ecfbf8SJan Medala if (rc != 0) { 2513ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reset indication didn't turn on\n"); 251499ecfbf8SJan Medala return rc; 251599ecfbf8SJan Medala } 251699ecfbf8SJan Medala 251799ecfbf8SJan Medala /* reset done */ 25183adcba9aSMichal Krawczyk ENA_REG_WRITE32(ena_dev->bus, 0, ena_dev->reg_bar + ENA_REGS_DEV_CTL_OFF); 251999ecfbf8SJan Medala rc = wait_for_reset_state(ena_dev, timeout, 0); 252099ecfbf8SJan Medala if (rc != 0) { 2521ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Reset indication didn't turn off\n"); 252299ecfbf8SJan Medala return rc; 252399ecfbf8SJan Medala } 252499ecfbf8SJan Medala 25253adcba9aSMichal Krawczyk timeout = (cap & ENA_REGS_CAPS_ADMIN_CMD_TO_MASK) >> 25263adcba9aSMichal Krawczyk ENA_REGS_CAPS_ADMIN_CMD_TO_SHIFT; 25273adcba9aSMichal Krawczyk if (timeout) 25283adcba9aSMichal Krawczyk /* the resolution of timeout reg is 100ms */ 25293adcba9aSMichal Krawczyk ena_dev->admin_queue.completion_timeout = timeout * 100000; 25303adcba9aSMichal Krawczyk else 25313adcba9aSMichal Krawczyk ena_dev->admin_queue.completion_timeout = ADMIN_CMD_TIMEOUT_US; 25323adcba9aSMichal Krawczyk 253399ecfbf8SJan Medala return 0; 253499ecfbf8SJan Medala } 253599ecfbf8SJan Medala 25360d09cbc7SMichal Krawczyk int ena_com_get_eni_stats(struct ena_com_dev *ena_dev, 25370d09cbc7SMichal Krawczyk struct ena_admin_eni_stats *stats) 25380d09cbc7SMichal Krawczyk { 25390d09cbc7SMichal Krawczyk struct ena_com_stats_ctx ctx; 25400d09cbc7SMichal Krawczyk int ret; 25410d09cbc7SMichal Krawczyk 2542f73f53f7SShai Brandes if (!ena_com_get_cap(ena_dev, ENA_ADMIN_ENI_STATS)) { 2543f73f53f7SShai Brandes ena_trc_err(ena_dev, "Capability %d isn't supported\n", ENA_ADMIN_ENI_STATS); 2544f73f53f7SShai Brandes return ENA_COM_UNSUPPORTED; 2545f73f53f7SShai Brandes } 2546f73f53f7SShai Brandes 25470d09cbc7SMichal Krawczyk memset(&ctx, 0x0, sizeof(ctx)); 25480d09cbc7SMichal Krawczyk ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENI); 25490d09cbc7SMichal Krawczyk if (likely(ret == 0)) 25500d09cbc7SMichal Krawczyk memcpy(stats, &ctx.get_resp.u.eni_stats, 25510d09cbc7SMichal Krawczyk sizeof(ctx.get_resp.u.eni_stats)); 25520d09cbc7SMichal Krawczyk 25530d09cbc7SMichal Krawczyk return ret; 25540d09cbc7SMichal Krawczyk } 25550d09cbc7SMichal Krawczyk 2556f73f53f7SShai Brandes int ena_com_get_ena_srd_info(struct ena_com_dev *ena_dev, 2557f73f53f7SShai Brandes struct ena_admin_ena_srd_info *info) 2558f73f53f7SShai Brandes { 2559f73f53f7SShai Brandes struct ena_com_stats_ctx ctx; 2560f73f53f7SShai Brandes int ret; 2561f73f53f7SShai Brandes 2562f73f53f7SShai Brandes if (!ena_com_get_cap(ena_dev, ENA_ADMIN_ENA_SRD_INFO)) { 2563f73f53f7SShai Brandes ena_trc_err(ena_dev, "Capability %d isn't supported\n", ENA_ADMIN_ENA_SRD_INFO); 2564f73f53f7SShai Brandes return ENA_COM_UNSUPPORTED; 2565f73f53f7SShai Brandes } 2566f73f53f7SShai Brandes 2567f73f53f7SShai Brandes memset(&ctx, 0x0, sizeof(ctx)); 2568f73f53f7SShai Brandes ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENA_SRD); 2569f73f53f7SShai Brandes if (likely(ret == 0)) 2570f73f53f7SShai Brandes memcpy(info, &ctx.get_resp.u.ena_srd_info, 2571f73f53f7SShai Brandes sizeof(ctx.get_resp.u.ena_srd_info)); 2572f73f53f7SShai Brandes 2573f73f53f7SShai Brandes return ret; 2574f73f53f7SShai Brandes } 2575f73f53f7SShai Brandes 257699ecfbf8SJan Medala int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev, 257799ecfbf8SJan Medala struct ena_admin_basic_stats *stats) 257899ecfbf8SJan Medala { 25793adcba9aSMichal Krawczyk struct ena_com_stats_ctx ctx; 25803adcba9aSMichal Krawczyk int ret; 258199ecfbf8SJan Medala 25823adcba9aSMichal Krawczyk memset(&ctx, 0x0, sizeof(ctx)); 25833adcba9aSMichal Krawczyk ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_BASIC); 258499ecfbf8SJan Medala if (likely(ret == 0)) 25850d09cbc7SMichal Krawczyk memcpy(stats, &ctx.get_resp.u.basic_stats, 25860d09cbc7SMichal Krawczyk sizeof(ctx.get_resp.u.basic_stats)); 258799ecfbf8SJan Medala 258899ecfbf8SJan Medala return ret; 258999ecfbf8SJan Medala } 259099ecfbf8SJan Medala 2591f73f53f7SShai Brandes int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32 len) 2592f73f53f7SShai Brandes { 2593f73f53f7SShai Brandes struct ena_admin_aq_get_stats_cmd *get_cmd; 2594f73f53f7SShai Brandes struct ena_com_stats_ctx ctx; 2595f73f53f7SShai Brandes int ret; 2596f73f53f7SShai Brandes 2597f73f53f7SShai Brandes if (unlikely(len > ena_dev->customer_metrics.buffer_len)) { 2598f73f53f7SShai Brandes ena_trc_err(ena_dev, "Invalid buffer size %u. The given buffer is too big.\n", len); 2599f73f53f7SShai Brandes return ENA_COM_INVAL; 2600f73f53f7SShai Brandes } 2601f73f53f7SShai Brandes 2602f73f53f7SShai Brandes if (!ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) { 2603f73f53f7SShai Brandes ena_trc_err(ena_dev, "Capability %d not supported.\n", ENA_ADMIN_CUSTOMER_METRICS); 2604f73f53f7SShai Brandes return ENA_COM_UNSUPPORTED; 2605f73f53f7SShai Brandes } 2606f73f53f7SShai Brandes 2607f73f53f7SShai Brandes if (!ena_dev->customer_metrics.supported_metrics) { 2608f73f53f7SShai Brandes ena_trc_err(ena_dev, "No supported customer metrics.\n"); 2609f73f53f7SShai Brandes return ENA_COM_UNSUPPORTED; 2610f73f53f7SShai Brandes } 2611f73f53f7SShai Brandes 2612f73f53f7SShai Brandes get_cmd = &ctx.get_cmd; 2613f73f53f7SShai Brandes memset(&ctx, 0x0, sizeof(ctx)); 2614f73f53f7SShai Brandes ret = ena_com_mem_addr_set(ena_dev, 2615f73f53f7SShai Brandes &get_cmd->u.control_buffer.address, 2616f73f53f7SShai Brandes ena_dev->customer_metrics.buffer_dma_addr); 2617f73f53f7SShai Brandes if (unlikely(ret)) { 2618f73f53f7SShai Brandes ena_trc_err(ena_dev, "Memory address set failed.\n"); 2619f73f53f7SShai Brandes return ret; 2620f73f53f7SShai Brandes } 2621f73f53f7SShai Brandes 2622f73f53f7SShai Brandes get_cmd->u.control_buffer.length = ena_dev->customer_metrics.buffer_len; 2623f73f53f7SShai Brandes get_cmd->requested_metrics = ena_dev->customer_metrics.supported_metrics; 2624f73f53f7SShai Brandes ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS); 2625f73f53f7SShai Brandes if (likely(ret == 0)) 2626f73f53f7SShai Brandes memcpy(buffer, ena_dev->customer_metrics.buffer_virt_addr, len); 2627f73f53f7SShai Brandes else 2628f73f53f7SShai Brandes ena_trc_err(ena_dev, "Failed to get customer metrics. error: %d\n", ret); 2629f73f53f7SShai Brandes 2630f73f53f7SShai Brandes return ret; 2631f73f53f7SShai Brandes } 2632f73f53f7SShai Brandes 2633f73f53f7SShai Brandes int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, u32 mtu) 263499ecfbf8SJan Medala { 263599ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 263699ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 263799ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 26383adcba9aSMichal Krawczyk int ret; 263999ecfbf8SJan Medala 264099ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_MTU)) { 2641ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Feature %d isn't supported\n", ENA_ADMIN_MTU); 26423adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 264399ecfbf8SJan Medala } 264499ecfbf8SJan Medala 264599ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 264699ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 264799ecfbf8SJan Medala 264899ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 264999ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 0; 265099ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_MTU; 2651f73f53f7SShai Brandes cmd.u.mtu.mtu = mtu; 265299ecfbf8SJan Medala 265399ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 265499ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 265599ecfbf8SJan Medala sizeof(cmd), 265699ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 265799ecfbf8SJan Medala sizeof(resp)); 265899ecfbf8SJan Medala 26593adcba9aSMichal Krawczyk if (unlikely(ret)) 2660ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to set mtu %d. error: %d\n", mtu, ret); 26613adcba9aSMichal Krawczyk 26623adcba9aSMichal Krawczyk return ret; 266399ecfbf8SJan Medala } 266499ecfbf8SJan Medala 266599ecfbf8SJan Medala int ena_com_get_offload_settings(struct ena_com_dev *ena_dev, 266699ecfbf8SJan Medala struct ena_admin_feature_offload_desc *offload) 266799ecfbf8SJan Medala { 266899ecfbf8SJan Medala int ret; 266999ecfbf8SJan Medala struct ena_admin_get_feat_resp resp; 267099ecfbf8SJan Medala 267199ecfbf8SJan Medala ret = ena_com_get_feature(ena_dev, &resp, 2672b68309beSRafal Kozik ENA_ADMIN_STATELESS_OFFLOAD_CONFIG, 0); 267399ecfbf8SJan Medala if (unlikely(ret)) { 2674ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to get offload capabilities %d\n", ret); 26753adcba9aSMichal Krawczyk return ret; 267699ecfbf8SJan Medala } 267799ecfbf8SJan Medala 267899ecfbf8SJan Medala memcpy(offload, &resp.u.offload, sizeof(resp.u.offload)); 267999ecfbf8SJan Medala 268099ecfbf8SJan Medala return 0; 268199ecfbf8SJan Medala } 268299ecfbf8SJan Medala 268399ecfbf8SJan Medala int ena_com_set_hash_function(struct ena_com_dev *ena_dev) 268499ecfbf8SJan Medala { 268599ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 268699ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 268799ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 268899ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 268999ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 269099ecfbf8SJan Medala int ret; 269199ecfbf8SJan Medala 269299ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, 269399ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION)) { 2694ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Feature %d isn't supported\n", 269599ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION); 26963adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 269799ecfbf8SJan Medala } 269899ecfbf8SJan Medala 269999ecfbf8SJan Medala /* Validate hash function is supported */ 270099ecfbf8SJan Medala ret = ena_com_get_feature(ena_dev, &get_resp, 2701b68309beSRafal Kozik ENA_ADMIN_RSS_HASH_FUNCTION, 0); 270299ecfbf8SJan Medala if (unlikely(ret)) 270399ecfbf8SJan Medala return ret; 270499ecfbf8SJan Medala 2705b2b02edeSMichal Krawczyk if (!(get_resp.u.flow_hash_func.supported_func & BIT(rss->hash_func))) { 2706ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Func hash %d isn't supported by device, abort\n", 270799ecfbf8SJan Medala rss->hash_func); 27083adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 270999ecfbf8SJan Medala } 271099ecfbf8SJan Medala 271199ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 271299ecfbf8SJan Medala 271399ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 271499ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 271599ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 271699ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_RSS_HASH_FUNCTION; 271799ecfbf8SJan Medala cmd.u.flow_hash_func.init_val = rss->hash_init_val; 271899ecfbf8SJan Medala cmd.u.flow_hash_func.selected_func = 1 << rss->hash_func; 271999ecfbf8SJan Medala 272099ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 272199ecfbf8SJan Medala &cmd.control_buffer.address, 272299ecfbf8SJan Medala rss->hash_key_dma_addr); 272399ecfbf8SJan Medala if (unlikely(ret)) { 2724ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 272599ecfbf8SJan Medala return ret; 272699ecfbf8SJan Medala } 272799ecfbf8SJan Medala 272899ecfbf8SJan Medala cmd.control_buffer.length = sizeof(*rss->hash_key); 272999ecfbf8SJan Medala 273099ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 273199ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 273299ecfbf8SJan Medala sizeof(cmd), 273399ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 273499ecfbf8SJan Medala sizeof(resp)); 273599ecfbf8SJan Medala if (unlikely(ret)) { 2736ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to set hash function %d. error: %d\n", 273799ecfbf8SJan Medala rss->hash_func, ret); 273899ecfbf8SJan Medala return ENA_COM_INVAL; 273999ecfbf8SJan Medala } 274099ecfbf8SJan Medala 274199ecfbf8SJan Medala return 0; 274299ecfbf8SJan Medala } 274399ecfbf8SJan Medala 274499ecfbf8SJan Medala int ena_com_fill_hash_function(struct ena_com_dev *ena_dev, 274599ecfbf8SJan Medala enum ena_admin_hash_functions func, 274699ecfbf8SJan Medala const u8 *key, u16 key_len, u32 init_val) 274799ecfbf8SJan Medala { 27486e585db6SMichal Krawczyk struct ena_admin_feature_rss_flow_hash_control *hash_key; 274999ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 27506e585db6SMichal Krawczyk enum ena_admin_hash_functions old_func; 27516e585db6SMichal Krawczyk struct ena_rss *rss = &ena_dev->rss; 275299ecfbf8SJan Medala int rc; 275399ecfbf8SJan Medala 27546e585db6SMichal Krawczyk hash_key = rss->hash_key; 27556e585db6SMichal Krawczyk 275699ecfbf8SJan Medala /* Make sure size is a mult of DWs */ 275799ecfbf8SJan Medala if (unlikely(key_len & 0x3)) 275899ecfbf8SJan Medala return ENA_COM_INVAL; 275999ecfbf8SJan Medala 276099ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 276199ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION, 276299ecfbf8SJan Medala rss->hash_key_dma_addr, 2763b68309beSRafal Kozik sizeof(*rss->hash_key), 0); 276499ecfbf8SJan Medala if (unlikely(rc)) 276599ecfbf8SJan Medala return rc; 276699ecfbf8SJan Medala 27676e585db6SMichal Krawczyk if (!(BIT(func) & get_resp.u.flow_hash_func.supported_func)) { 2768ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Flow hash function %d isn't supported\n", func); 27693adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 277099ecfbf8SJan Medala } 277199ecfbf8SJan Medala 2772f73f53f7SShai Brandes if (func == ENA_ADMIN_TOEPLITZ && key) { 2773086c6b66SMichal Krawczyk if (key_len != sizeof(hash_key->key)) { 2774f73f53f7SShai Brandes ena_trc_err(ena_dev, "key len (%u) doesn't equal the supported size (%zu)\n", 277599ecfbf8SJan Medala key_len, sizeof(hash_key->key)); 277699ecfbf8SJan Medala return ENA_COM_INVAL; 277799ecfbf8SJan Medala } 277899ecfbf8SJan Medala memcpy(hash_key->key, key, key_len); 2779b19f366cSMichal Krawczyk hash_key->key_parts = key_len / sizeof(hash_key->key[0]); 2780086c6b66SMichal Krawczyk } 278199ecfbf8SJan Medala 2782f73f53f7SShai Brandes rss->hash_init_val = init_val; 27836e585db6SMichal Krawczyk old_func = rss->hash_func; 2784b2b02edeSMichal Krawczyk rss->hash_func = func; 278599ecfbf8SJan Medala rc = ena_com_set_hash_function(ena_dev); 278699ecfbf8SJan Medala 278799ecfbf8SJan Medala /* Restore the old function */ 278899ecfbf8SJan Medala if (unlikely(rc)) 27896e585db6SMichal Krawczyk rss->hash_func = old_func; 279099ecfbf8SJan Medala 279199ecfbf8SJan Medala return rc; 279299ecfbf8SJan Medala } 279399ecfbf8SJan Medala 279499ecfbf8SJan Medala int ena_com_get_hash_function(struct ena_com_dev *ena_dev, 27953e55684eSMichal Krawczyk enum ena_admin_hash_functions *func) 279699ecfbf8SJan Medala { 279799ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 279899ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 279999ecfbf8SJan Medala int rc; 280099ecfbf8SJan Medala 28013e55684eSMichal Krawczyk if (unlikely(!func)) 28023e55684eSMichal Krawczyk return ENA_COM_INVAL; 28033e55684eSMichal Krawczyk 280499ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 280599ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_FUNCTION, 280699ecfbf8SJan Medala rss->hash_key_dma_addr, 2807b68309beSRafal Kozik sizeof(*rss->hash_key), 0); 280899ecfbf8SJan Medala if (unlikely(rc)) 280999ecfbf8SJan Medala return rc; 281099ecfbf8SJan Medala 28113e55684eSMichal Krawczyk /* ENA_FFS() returns 1 in case the lsb is set */ 28126e585db6SMichal Krawczyk rss->hash_func = ENA_FFS(get_resp.u.flow_hash_func.selected_func); 28136e585db6SMichal Krawczyk if (rss->hash_func) 28146e585db6SMichal Krawczyk rss->hash_func--; 28156e585db6SMichal Krawczyk 281699ecfbf8SJan Medala *func = rss->hash_func; 281799ecfbf8SJan Medala 28183e55684eSMichal Krawczyk return 0; 28193e55684eSMichal Krawczyk } 28203e55684eSMichal Krawczyk 28213e55684eSMichal Krawczyk int ena_com_get_hash_key(struct ena_com_dev *ena_dev, u8 *key) 28223e55684eSMichal Krawczyk { 28233e55684eSMichal Krawczyk struct ena_admin_feature_rss_flow_hash_control *hash_key = 28243e55684eSMichal Krawczyk ena_dev->rss.hash_key; 28253e55684eSMichal Krawczyk 282699ecfbf8SJan Medala if (key) 2827b19f366cSMichal Krawczyk memcpy(key, hash_key->key, 2828b19f366cSMichal Krawczyk (size_t)(hash_key->key_parts) * sizeof(hash_key->key[0])); 282999ecfbf8SJan Medala 283099ecfbf8SJan Medala return 0; 283199ecfbf8SJan Medala } 283299ecfbf8SJan Medala 283399ecfbf8SJan Medala int ena_com_get_hash_ctrl(struct ena_com_dev *ena_dev, 283499ecfbf8SJan Medala enum ena_admin_flow_hash_proto proto, 283599ecfbf8SJan Medala u16 *fields) 283699ecfbf8SJan Medala { 283799ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 283899ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 283999ecfbf8SJan Medala int rc; 284099ecfbf8SJan Medala 284199ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 284299ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_INPUT, 284399ecfbf8SJan Medala rss->hash_ctrl_dma_addr, 2844b68309beSRafal Kozik sizeof(*rss->hash_ctrl), 0); 284599ecfbf8SJan Medala if (unlikely(rc)) 284699ecfbf8SJan Medala return rc; 284799ecfbf8SJan Medala 284899ecfbf8SJan Medala if (fields) 284999ecfbf8SJan Medala *fields = rss->hash_ctrl->selected_fields[proto].fields; 285099ecfbf8SJan Medala 285199ecfbf8SJan Medala return 0; 285299ecfbf8SJan Medala } 285399ecfbf8SJan Medala 285499ecfbf8SJan Medala int ena_com_set_hash_ctrl(struct ena_com_dev *ena_dev) 285599ecfbf8SJan Medala { 285699ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 285799ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 28583adcba9aSMichal Krawczyk struct ena_admin_feature_rss_hash_control *hash_ctrl = rss->hash_ctrl; 285999ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 286099ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 286199ecfbf8SJan Medala int ret; 286299ecfbf8SJan Medala 286399ecfbf8SJan Medala if (!ena_com_check_supported_feature_id(ena_dev, 286499ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_INPUT)) { 2865ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Feature %d isn't supported\n", 286699ecfbf8SJan Medala ENA_ADMIN_RSS_HASH_INPUT); 28673adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 286899ecfbf8SJan Medala } 286999ecfbf8SJan Medala 28703adcba9aSMichal Krawczyk memset(&cmd, 0x0, sizeof(cmd)); 28713adcba9aSMichal Krawczyk 287299ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 287399ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 287499ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 287599ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_RSS_HASH_INPUT; 287699ecfbf8SJan Medala cmd.u.flow_hash_input.enabled_input_sort = 287799ecfbf8SJan Medala ENA_ADMIN_FEATURE_RSS_FLOW_HASH_INPUT_L3_SORT_MASK | 287899ecfbf8SJan Medala ENA_ADMIN_FEATURE_RSS_FLOW_HASH_INPUT_L4_SORT_MASK; 287999ecfbf8SJan Medala 288099ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 288199ecfbf8SJan Medala &cmd.control_buffer.address, 288299ecfbf8SJan Medala rss->hash_ctrl_dma_addr); 288399ecfbf8SJan Medala if (unlikely(ret)) { 2884ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 288599ecfbf8SJan Medala return ret; 288699ecfbf8SJan Medala } 28873adcba9aSMichal Krawczyk cmd.control_buffer.length = sizeof(*hash_ctrl); 288899ecfbf8SJan Medala 288999ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 289099ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 289199ecfbf8SJan Medala sizeof(cmd), 289299ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 289399ecfbf8SJan Medala sizeof(resp)); 28943adcba9aSMichal Krawczyk if (unlikely(ret)) 2895ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to set hash input. error: %d\n", ret); 289699ecfbf8SJan Medala 28973adcba9aSMichal Krawczyk return ret; 289899ecfbf8SJan Medala } 289999ecfbf8SJan Medala 290099ecfbf8SJan Medala int ena_com_set_default_hash_ctrl(struct ena_com_dev *ena_dev) 290199ecfbf8SJan Medala { 290299ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 290399ecfbf8SJan Medala struct ena_admin_feature_rss_hash_control *hash_ctrl = 290499ecfbf8SJan Medala rss->hash_ctrl; 290599ecfbf8SJan Medala u16 available_fields = 0; 290699ecfbf8SJan Medala int rc, i; 290799ecfbf8SJan Medala 290899ecfbf8SJan Medala /* Get the supported hash input */ 29093adcba9aSMichal Krawczyk rc = ena_com_get_hash_ctrl(ena_dev, 0, NULL); 291099ecfbf8SJan Medala if (unlikely(rc)) 291199ecfbf8SJan Medala return rc; 291299ecfbf8SJan Medala 291399ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_TCP4].fields = 291499ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 291599ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 291699ecfbf8SJan Medala 291799ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_UDP4].fields = 291899ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 291999ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 292099ecfbf8SJan Medala 292199ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_TCP6].fields = 292299ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 292399ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 292499ecfbf8SJan Medala 292599ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_UDP6].fields = 292699ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA | 292799ecfbf8SJan Medala ENA_ADMIN_RSS_L4_DP | ENA_ADMIN_RSS_L4_SP; 292899ecfbf8SJan Medala 292999ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP4].fields = 293099ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA; 293199ecfbf8SJan Medala 293299ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP6].fields = 293399ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA; 293499ecfbf8SJan Medala 293599ecfbf8SJan Medala hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP4_FRAG].fields = 293699ecfbf8SJan Medala ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA; 293799ecfbf8SJan Medala 29383adcba9aSMichal Krawczyk hash_ctrl->selected_fields[ENA_ADMIN_RSS_NOT_IP].fields = 293999ecfbf8SJan Medala ENA_ADMIN_RSS_L2_DA | ENA_ADMIN_RSS_L2_SA; 294099ecfbf8SJan Medala 294199ecfbf8SJan Medala for (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; i++) { 294299ecfbf8SJan Medala available_fields = hash_ctrl->selected_fields[i].fields & 294399ecfbf8SJan Medala hash_ctrl->supported_fields[i].fields; 294499ecfbf8SJan Medala if (available_fields != hash_ctrl->selected_fields[i].fields) { 2945ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Hash control doesn't support all the desire configuration. proto %x supported %x selected %x\n", 294699ecfbf8SJan Medala i, hash_ctrl->supported_fields[i].fields, 294799ecfbf8SJan Medala hash_ctrl->selected_fields[i].fields); 29483adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 294999ecfbf8SJan Medala } 295099ecfbf8SJan Medala } 295199ecfbf8SJan Medala 295299ecfbf8SJan Medala rc = ena_com_set_hash_ctrl(ena_dev); 295399ecfbf8SJan Medala 295499ecfbf8SJan Medala /* In case of failure, restore the old hash ctrl */ 295599ecfbf8SJan Medala if (unlikely(rc)) 29563adcba9aSMichal Krawczyk ena_com_get_hash_ctrl(ena_dev, 0, NULL); 295799ecfbf8SJan Medala 295899ecfbf8SJan Medala return rc; 295999ecfbf8SJan Medala } 296099ecfbf8SJan Medala 296199ecfbf8SJan Medala int ena_com_fill_hash_ctrl(struct ena_com_dev *ena_dev, 296299ecfbf8SJan Medala enum ena_admin_flow_hash_proto proto, 296399ecfbf8SJan Medala u16 hash_fields) 296499ecfbf8SJan Medala { 296599ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 296699ecfbf8SJan Medala struct ena_admin_feature_rss_hash_control *hash_ctrl = rss->hash_ctrl; 296799ecfbf8SJan Medala u16 supported_fields; 296899ecfbf8SJan Medala int rc; 296999ecfbf8SJan Medala 29706dcee7cdSJan Medala if (proto >= ENA_ADMIN_RSS_PROTO_NUM) { 2971ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Invalid proto num (%u)\n", proto); 297299ecfbf8SJan Medala return ENA_COM_INVAL; 297399ecfbf8SJan Medala } 297499ecfbf8SJan Medala 297599ecfbf8SJan Medala /* Get the ctrl table */ 297699ecfbf8SJan Medala rc = ena_com_get_hash_ctrl(ena_dev, proto, NULL); 297799ecfbf8SJan Medala if (unlikely(rc)) 297899ecfbf8SJan Medala return rc; 297999ecfbf8SJan Medala 298099ecfbf8SJan Medala /* Make sure all the fields are supported */ 298199ecfbf8SJan Medala supported_fields = hash_ctrl->supported_fields[proto].fields; 298299ecfbf8SJan Medala if ((hash_fields & supported_fields) != hash_fields) { 2983ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Proto %d doesn't support the required fields %x. supports only: %x\n", 298499ecfbf8SJan Medala proto, hash_fields, supported_fields); 298599ecfbf8SJan Medala } 298699ecfbf8SJan Medala 298799ecfbf8SJan Medala hash_ctrl->selected_fields[proto].fields = hash_fields; 298899ecfbf8SJan Medala 298999ecfbf8SJan Medala rc = ena_com_set_hash_ctrl(ena_dev); 299099ecfbf8SJan Medala 299199ecfbf8SJan Medala /* In case of failure, restore the old hash ctrl */ 299299ecfbf8SJan Medala if (unlikely(rc)) 29933adcba9aSMichal Krawczyk ena_com_get_hash_ctrl(ena_dev, 0, NULL); 299499ecfbf8SJan Medala 299599ecfbf8SJan Medala return 0; 299699ecfbf8SJan Medala } 299799ecfbf8SJan Medala 299899ecfbf8SJan Medala int ena_com_indirect_table_fill_entry(struct ena_com_dev *ena_dev, 299999ecfbf8SJan Medala u16 entry_idx, u16 entry_value) 300099ecfbf8SJan Medala { 300199ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 300299ecfbf8SJan Medala 300399ecfbf8SJan Medala if (unlikely(entry_idx >= (1 << rss->tbl_log_size))) 300499ecfbf8SJan Medala return ENA_COM_INVAL; 300599ecfbf8SJan Medala 300699ecfbf8SJan Medala if (unlikely((entry_value > ENA_TOTAL_NUM_QUEUES))) 300799ecfbf8SJan Medala return ENA_COM_INVAL; 300899ecfbf8SJan Medala 300999ecfbf8SJan Medala rss->host_rss_ind_tbl[entry_idx] = entry_value; 301099ecfbf8SJan Medala 301199ecfbf8SJan Medala return 0; 301299ecfbf8SJan Medala } 301399ecfbf8SJan Medala 301499ecfbf8SJan Medala int ena_com_indirect_table_set(struct ena_com_dev *ena_dev) 301599ecfbf8SJan Medala { 301699ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue; 301799ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 301899ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 301999ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 30203adcba9aSMichal Krawczyk int ret; 302199ecfbf8SJan Medala 30223adcba9aSMichal Krawczyk if (!ena_com_check_supported_feature_id(ena_dev, 3023b19f366cSMichal Krawczyk ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG)) { 3024ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Feature %d isn't supported\n", 3025b19f366cSMichal Krawczyk ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG); 30263adcba9aSMichal Krawczyk return ENA_COM_UNSUPPORTED; 302799ecfbf8SJan Medala } 302899ecfbf8SJan Medala 302999ecfbf8SJan Medala ret = ena_com_ind_tbl_convert_to_device(ena_dev); 303099ecfbf8SJan Medala if (ret) { 3031ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to convert host indirection table to device table\n"); 303299ecfbf8SJan Medala return ret; 303399ecfbf8SJan Medala } 303499ecfbf8SJan Medala 303599ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 303699ecfbf8SJan Medala 303799ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 303899ecfbf8SJan Medala cmd.aq_common_descriptor.flags = 303999ecfbf8SJan Medala ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; 3040b19f366cSMichal Krawczyk cmd.feat_common.feature_id = ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG; 304199ecfbf8SJan Medala cmd.u.ind_table.size = rss->tbl_log_size; 304299ecfbf8SJan Medala cmd.u.ind_table.inline_index = 0xFFFFFFFF; 304399ecfbf8SJan Medala 304499ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 304599ecfbf8SJan Medala &cmd.control_buffer.address, 304699ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr); 304799ecfbf8SJan Medala if (unlikely(ret)) { 3048ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 304999ecfbf8SJan Medala return ret; 305099ecfbf8SJan Medala } 305199ecfbf8SJan Medala 3052f73f53f7SShai Brandes cmd.control_buffer.length = (1ULL << rss->tbl_log_size) * 305399ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 305499ecfbf8SJan Medala 305599ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 305699ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 305799ecfbf8SJan Medala sizeof(cmd), 305899ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 305999ecfbf8SJan Medala sizeof(resp)); 306099ecfbf8SJan Medala 30613adcba9aSMichal Krawczyk if (unlikely(ret)) 3062ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to set indirect table. error: %d\n", ret); 306399ecfbf8SJan Medala 30643adcba9aSMichal Krawczyk return ret; 306599ecfbf8SJan Medala } 306699ecfbf8SJan Medala 306799ecfbf8SJan Medala int ena_com_indirect_table_get(struct ena_com_dev *ena_dev, u32 *ind_tbl) 306899ecfbf8SJan Medala { 306999ecfbf8SJan Medala struct ena_rss *rss = &ena_dev->rss; 307099ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 307199ecfbf8SJan Medala u32 tbl_size; 307299ecfbf8SJan Medala int i, rc; 307399ecfbf8SJan Medala 3074f73f53f7SShai Brandes tbl_size = (1ULL << rss->tbl_log_size) * 307599ecfbf8SJan Medala sizeof(struct ena_admin_rss_ind_table_entry); 307699ecfbf8SJan Medala 307799ecfbf8SJan Medala rc = ena_com_get_feature_ex(ena_dev, &get_resp, 3078b19f366cSMichal Krawczyk ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG, 307999ecfbf8SJan Medala rss->rss_ind_tbl_dma_addr, 3080b68309beSRafal Kozik tbl_size, 0); 308199ecfbf8SJan Medala if (unlikely(rc)) 308299ecfbf8SJan Medala return rc; 308399ecfbf8SJan Medala 308499ecfbf8SJan Medala if (!ind_tbl) 308599ecfbf8SJan Medala return 0; 308699ecfbf8SJan Medala 308799ecfbf8SJan Medala for (i = 0; i < (1 << rss->tbl_log_size); i++) 308899ecfbf8SJan Medala ind_tbl[i] = rss->host_rss_ind_tbl[i]; 308999ecfbf8SJan Medala 309099ecfbf8SJan Medala return 0; 309199ecfbf8SJan Medala } 309299ecfbf8SJan Medala 309399ecfbf8SJan Medala int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 indr_tbl_log_size) 309499ecfbf8SJan Medala { 309599ecfbf8SJan Medala int rc; 309699ecfbf8SJan Medala 309799ecfbf8SJan Medala memset(&ena_dev->rss, 0x0, sizeof(ena_dev->rss)); 309899ecfbf8SJan Medala 309999ecfbf8SJan Medala rc = ena_com_indirect_table_allocate(ena_dev, indr_tbl_log_size); 310099ecfbf8SJan Medala if (unlikely(rc)) 310199ecfbf8SJan Medala goto err_indr_tbl; 310299ecfbf8SJan Medala 3103ff40db8dSMichal Krawczyk /* The following function might return unsupported in case the 3104ff40db8dSMichal Krawczyk * device doesn't support setting the key / hash function. We can safely 3105ff40db8dSMichal Krawczyk * ignore this error and have indirection table support only. 3106ff40db8dSMichal Krawczyk */ 310799ecfbf8SJan Medala rc = ena_com_hash_key_allocate(ena_dev); 3108ff40db8dSMichal Krawczyk if (likely(!rc)) 3109086c6b66SMichal Krawczyk ena_com_hash_key_fill_default_key(ena_dev); 3110ff40db8dSMichal Krawczyk else if (rc != ENA_COM_UNSUPPORTED) 3111ff40db8dSMichal Krawczyk goto err_hash_key; 3112086c6b66SMichal Krawczyk 311399ecfbf8SJan Medala rc = ena_com_hash_ctrl_init(ena_dev); 311499ecfbf8SJan Medala if (unlikely(rc)) 311599ecfbf8SJan Medala goto err_hash_ctrl; 311699ecfbf8SJan Medala 311799ecfbf8SJan Medala return 0; 311899ecfbf8SJan Medala 311999ecfbf8SJan Medala err_hash_ctrl: 312099ecfbf8SJan Medala ena_com_hash_key_destroy(ena_dev); 312199ecfbf8SJan Medala err_hash_key: 312299ecfbf8SJan Medala ena_com_indirect_table_destroy(ena_dev); 312399ecfbf8SJan Medala err_indr_tbl: 312499ecfbf8SJan Medala 312599ecfbf8SJan Medala return rc; 312699ecfbf8SJan Medala } 312799ecfbf8SJan Medala 31286dcee7cdSJan Medala void ena_com_rss_destroy(struct ena_com_dev *ena_dev) 312999ecfbf8SJan Medala { 313099ecfbf8SJan Medala ena_com_indirect_table_destroy(ena_dev); 313199ecfbf8SJan Medala ena_com_hash_key_destroy(ena_dev); 313299ecfbf8SJan Medala ena_com_hash_ctrl_destroy(ena_dev); 313399ecfbf8SJan Medala 313499ecfbf8SJan Medala memset(&ena_dev->rss, 0x0, sizeof(ena_dev->rss)); 313599ecfbf8SJan Medala } 313699ecfbf8SJan Medala 31376dcee7cdSJan Medala int ena_com_allocate_host_info(struct ena_com_dev *ena_dev) 313899ecfbf8SJan Medala { 313999ecfbf8SJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 314099ecfbf8SJan Medala 314199ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 314299ecfbf8SJan Medala SZ_4K, 314399ecfbf8SJan Medala host_attr->host_info, 314499ecfbf8SJan Medala host_attr->host_info_dma_addr, 314599ecfbf8SJan Medala host_attr->host_info_dma_handle); 314699ecfbf8SJan Medala if (unlikely(!host_attr->host_info)) 314799ecfbf8SJan Medala return ENA_COM_NO_MEM; 314899ecfbf8SJan Medala 3149b68309beSRafal Kozik host_attr->host_info->ena_spec_version = ((ENA_COMMON_SPEC_VERSION_MAJOR << 3150b68309beSRafal Kozik ENA_REGS_VERSION_MAJOR_VERSION_SHIFT) | 3151b68309beSRafal Kozik (ENA_COMMON_SPEC_VERSION_MINOR)); 3152b68309beSRafal Kozik 31536dcee7cdSJan Medala return 0; 31546dcee7cdSJan Medala } 31556dcee7cdSJan Medala 31566dcee7cdSJan Medala int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev, 31573adcba9aSMichal Krawczyk u32 debug_area_size) 31583adcba9aSMichal Krawczyk { 31596dcee7cdSJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 31606dcee7cdSJan Medala 316199ecfbf8SJan Medala ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 316299ecfbf8SJan Medala debug_area_size, 316399ecfbf8SJan Medala host_attr->debug_area_virt_addr, 316499ecfbf8SJan Medala host_attr->debug_area_dma_addr, 316599ecfbf8SJan Medala host_attr->debug_area_dma_handle); 316699ecfbf8SJan Medala if (unlikely(!host_attr->debug_area_virt_addr)) { 31676dcee7cdSJan Medala host_attr->debug_area_size = 0; 31686dcee7cdSJan Medala return ENA_COM_NO_MEM; 316999ecfbf8SJan Medala } 317099ecfbf8SJan Medala 317199ecfbf8SJan Medala host_attr->debug_area_size = debug_area_size; 317299ecfbf8SJan Medala 317399ecfbf8SJan Medala return 0; 317499ecfbf8SJan Medala } 317599ecfbf8SJan Medala 3176f73f53f7SShai Brandes int ena_com_allocate_customer_metrics_buffer(struct ena_com_dev *ena_dev) 3177f73f53f7SShai Brandes { 3178f73f53f7SShai Brandes struct ena_customer_metrics *customer_metrics = &ena_dev->customer_metrics; 3179f73f53f7SShai Brandes 3180f73f53f7SShai Brandes ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev, 3181f73f53f7SShai Brandes customer_metrics->buffer_len, 3182f73f53f7SShai Brandes customer_metrics->buffer_virt_addr, 3183f73f53f7SShai Brandes customer_metrics->buffer_dma_addr, 3184f73f53f7SShai Brandes customer_metrics->buffer_dma_handle); 3185f73f53f7SShai Brandes if (unlikely(customer_metrics->buffer_virt_addr == NULL)) 3186f73f53f7SShai Brandes return ENA_COM_NO_MEM; 3187f73f53f7SShai Brandes 3188f73f53f7SShai Brandes customer_metrics->buffer_len = ENA_CUSTOMER_METRICS_BUFFER_SIZE; 3189f73f53f7SShai Brandes 3190f73f53f7SShai Brandes return 0; 3191f73f53f7SShai Brandes } 3192f73f53f7SShai Brandes 31936dcee7cdSJan Medala void ena_com_delete_host_info(struct ena_com_dev *ena_dev) 319499ecfbf8SJan Medala { 319599ecfbf8SJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 319699ecfbf8SJan Medala 319799ecfbf8SJan Medala if (host_attr->host_info) { 319899ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 319999ecfbf8SJan Medala SZ_4K, 320099ecfbf8SJan Medala host_attr->host_info, 320199ecfbf8SJan Medala host_attr->host_info_dma_addr, 320299ecfbf8SJan Medala host_attr->host_info_dma_handle); 320399ecfbf8SJan Medala host_attr->host_info = NULL; 320499ecfbf8SJan Medala } 32056dcee7cdSJan Medala } 32066dcee7cdSJan Medala 32076dcee7cdSJan Medala void ena_com_delete_debug_area(struct ena_com_dev *ena_dev) 32086dcee7cdSJan Medala { 32096dcee7cdSJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 321099ecfbf8SJan Medala 321199ecfbf8SJan Medala if (host_attr->debug_area_virt_addr) { 321299ecfbf8SJan Medala ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 321399ecfbf8SJan Medala host_attr->debug_area_size, 321499ecfbf8SJan Medala host_attr->debug_area_virt_addr, 321599ecfbf8SJan Medala host_attr->debug_area_dma_addr, 321699ecfbf8SJan Medala host_attr->debug_area_dma_handle); 321799ecfbf8SJan Medala host_attr->debug_area_virt_addr = NULL; 321899ecfbf8SJan Medala } 321999ecfbf8SJan Medala } 322099ecfbf8SJan Medala 3221f73f53f7SShai Brandes void ena_com_delete_customer_metrics_buffer(struct ena_com_dev *ena_dev) 3222f73f53f7SShai Brandes { 3223f73f53f7SShai Brandes struct ena_customer_metrics *customer_metrics = &ena_dev->customer_metrics; 3224f73f53f7SShai Brandes 3225f73f53f7SShai Brandes if (customer_metrics->buffer_virt_addr) { 3226f73f53f7SShai Brandes ENA_MEM_FREE_COHERENT(ena_dev->dmadev, 3227f73f53f7SShai Brandes customer_metrics->buffer_len, 3228f73f53f7SShai Brandes customer_metrics->buffer_virt_addr, 3229f73f53f7SShai Brandes customer_metrics->buffer_dma_addr, 3230f73f53f7SShai Brandes customer_metrics->buffer_dma_handle); 3231f73f53f7SShai Brandes customer_metrics->buffer_virt_addr = NULL; 3232f73f53f7SShai Brandes customer_metrics->buffer_len = 0; 3233f73f53f7SShai Brandes } 3234f73f53f7SShai Brandes } 3235f73f53f7SShai Brandes 323699ecfbf8SJan Medala int ena_com_set_host_attributes(struct ena_com_dev *ena_dev) 323799ecfbf8SJan Medala { 323899ecfbf8SJan Medala struct ena_host_attribute *host_attr = &ena_dev->host_attr; 323999ecfbf8SJan Medala struct ena_com_admin_queue *admin_queue; 324099ecfbf8SJan Medala struct ena_admin_set_feat_cmd cmd; 324199ecfbf8SJan Medala struct ena_admin_set_feat_resp resp; 32423adcba9aSMichal Krawczyk 3243201ff2e5SJakub Palider int ret; 324499ecfbf8SJan Medala 3245201ff2e5SJakub Palider /* Host attribute config is called before ena_com_get_dev_attr_feat 3246201ff2e5SJakub Palider * so ena_com can't check if the feature is supported. 3247201ff2e5SJakub Palider */ 324899ecfbf8SJan Medala 324999ecfbf8SJan Medala memset(&cmd, 0x0, sizeof(cmd)); 325099ecfbf8SJan Medala admin_queue = &ena_dev->admin_queue; 325199ecfbf8SJan Medala 325299ecfbf8SJan Medala cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; 325399ecfbf8SJan Medala cmd.feat_common.feature_id = ENA_ADMIN_HOST_ATTR_CONFIG; 325499ecfbf8SJan Medala 325599ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 325699ecfbf8SJan Medala &cmd.u.host_attr.debug_ba, 325799ecfbf8SJan Medala host_attr->debug_area_dma_addr); 325899ecfbf8SJan Medala if (unlikely(ret)) { 3259ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 326099ecfbf8SJan Medala return ret; 326199ecfbf8SJan Medala } 326299ecfbf8SJan Medala 326399ecfbf8SJan Medala ret = ena_com_mem_addr_set(ena_dev, 326499ecfbf8SJan Medala &cmd.u.host_attr.os_info_ba, 326599ecfbf8SJan Medala host_attr->host_info_dma_addr); 326699ecfbf8SJan Medala if (unlikely(ret)) { 3267ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Memory address set failed\n"); 326899ecfbf8SJan Medala return ret; 326999ecfbf8SJan Medala } 327099ecfbf8SJan Medala 327199ecfbf8SJan Medala cmd.u.host_attr.debug_area_size = host_attr->debug_area_size; 327299ecfbf8SJan Medala 327399ecfbf8SJan Medala ret = ena_com_execute_admin_command(admin_queue, 327499ecfbf8SJan Medala (struct ena_admin_aq_entry *)&cmd, 327599ecfbf8SJan Medala sizeof(cmd), 327699ecfbf8SJan Medala (struct ena_admin_acq_entry *)&resp, 327799ecfbf8SJan Medala sizeof(resp)); 327899ecfbf8SJan Medala 327999ecfbf8SJan Medala if (unlikely(ret)) 3280ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Failed to set host attributes: %d\n", ret); 328199ecfbf8SJan Medala 328299ecfbf8SJan Medala return ret; 328399ecfbf8SJan Medala } 328499ecfbf8SJan Medala 328599ecfbf8SJan Medala /* Interrupt moderation */ 328699ecfbf8SJan Medala bool ena_com_interrupt_moderation_supported(struct ena_com_dev *ena_dev) 328799ecfbf8SJan Medala { 32883adcba9aSMichal Krawczyk return ena_com_check_supported_feature_id(ena_dev, 328999ecfbf8SJan Medala ENA_ADMIN_INTERRUPT_MODERATION); 329099ecfbf8SJan Medala } 329199ecfbf8SJan Medala 3292ac2fd8a5SMichal Krawczyk static int ena_com_update_nonadaptive_moderation_interval(struct ena_com_dev *ena_dev, 3293ac2fd8a5SMichal Krawczyk u32 coalesce_usecs, 3294d2138b23SMichal Krawczyk u32 intr_delay_resolution, 3295d2138b23SMichal Krawczyk u32 *intr_moder_interval) 329699ecfbf8SJan Medala { 3297d2138b23SMichal Krawczyk if (!intr_delay_resolution) { 3298ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "Illegal interrupt delay granularity value\n"); 329999ecfbf8SJan Medala return ENA_COM_FAULT; 330099ecfbf8SJan Medala } 330199ecfbf8SJan Medala 3302d2138b23SMichal Krawczyk *intr_moder_interval = coalesce_usecs / intr_delay_resolution; 330399ecfbf8SJan Medala 330499ecfbf8SJan Medala return 0; 330599ecfbf8SJan Medala } 330699ecfbf8SJan Medala 3307d2138b23SMichal Krawczyk int ena_com_update_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev, 3308d2138b23SMichal Krawczyk u32 tx_coalesce_usecs) 3309d2138b23SMichal Krawczyk { 3310ac2fd8a5SMichal Krawczyk return ena_com_update_nonadaptive_moderation_interval(ena_dev, 3311ac2fd8a5SMichal Krawczyk tx_coalesce_usecs, 3312d2138b23SMichal Krawczyk ena_dev->intr_delay_resolution, 3313d2138b23SMichal Krawczyk &ena_dev->intr_moder_tx_interval); 3314d2138b23SMichal Krawczyk } 3315d2138b23SMichal Krawczyk 33163adcba9aSMichal Krawczyk int ena_com_update_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev, 331799ecfbf8SJan Medala u32 rx_coalesce_usecs) 331899ecfbf8SJan Medala { 3319ac2fd8a5SMichal Krawczyk return ena_com_update_nonadaptive_moderation_interval(ena_dev, 3320ac2fd8a5SMichal Krawczyk rx_coalesce_usecs, 3321d2138b23SMichal Krawczyk ena_dev->intr_delay_resolution, 3322d2138b23SMichal Krawczyk &ena_dev->intr_moder_rx_interval); 332399ecfbf8SJan Medala } 332499ecfbf8SJan Medala 332599ecfbf8SJan Medala int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev) 332699ecfbf8SJan Medala { 332799ecfbf8SJan Medala struct ena_admin_get_feat_resp get_resp; 33286dcee7cdSJan Medala u16 delay_resolution; 332999ecfbf8SJan Medala int rc; 333099ecfbf8SJan Medala 333199ecfbf8SJan Medala rc = ena_com_get_feature(ena_dev, &get_resp, 3332b68309beSRafal Kozik ENA_ADMIN_INTERRUPT_MODERATION, 0); 333399ecfbf8SJan Medala 333499ecfbf8SJan Medala if (rc) { 33353adcba9aSMichal Krawczyk if (rc == ENA_COM_UNSUPPORTED) { 3336ac2fd8a5SMichal Krawczyk ena_trc_dbg(ena_dev, "Feature %d isn't supported\n", 333799ecfbf8SJan Medala ENA_ADMIN_INTERRUPT_MODERATION); 333899ecfbf8SJan Medala rc = 0; 333999ecfbf8SJan Medala } else { 3340ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, 3341ac2fd8a5SMichal Krawczyk "Failed to get interrupt moderation admin cmd. rc: %d\n", rc); 334299ecfbf8SJan Medala } 334399ecfbf8SJan Medala 334499ecfbf8SJan Medala /* no moderation supported, disable adaptive support */ 334599ecfbf8SJan Medala ena_com_disable_adaptive_moderation(ena_dev); 334699ecfbf8SJan Medala return rc; 334799ecfbf8SJan Medala } 334899ecfbf8SJan Medala 334999ecfbf8SJan Medala /* if moderation is supported by device we set adaptive moderation */ 335099ecfbf8SJan Medala delay_resolution = get_resp.u.intr_moderation.intr_delay_resolution; 335199ecfbf8SJan Medala ena_com_update_intr_delay_resolution(ena_dev, delay_resolution); 3352b2b02edeSMichal Krawczyk 3353b2b02edeSMichal Krawczyk /* Disable adaptive moderation by default - can be enabled later */ 3354b2b02edeSMichal Krawczyk ena_com_disable_adaptive_moderation(ena_dev); 335599ecfbf8SJan Medala 335699ecfbf8SJan Medala return 0; 335799ecfbf8SJan Medala } 335899ecfbf8SJan Medala 33593adcba9aSMichal Krawczyk unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev) 336099ecfbf8SJan Medala { 336199ecfbf8SJan Medala return ena_dev->intr_moder_tx_interval; 336299ecfbf8SJan Medala } 336399ecfbf8SJan Medala 33643adcba9aSMichal Krawczyk unsigned int ena_com_get_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev) 336599ecfbf8SJan Medala { 3366d2138b23SMichal Krawczyk return ena_dev->intr_moder_rx_interval; 336799ecfbf8SJan Medala } 3368b68309beSRafal Kozik 3369b68309beSRafal Kozik int ena_com_config_dev_mode(struct ena_com_dev *ena_dev, 3370b68309beSRafal Kozik struct ena_admin_feature_llq_desc *llq_features, 3371b68309beSRafal Kozik struct ena_llq_configurations *llq_default_cfg) 3372b68309beSRafal Kozik { 33731e964c59SMichal Krawczyk struct ena_com_llq_info *llq_info = &ena_dev->llq_info; 3374b68309beSRafal Kozik int rc; 3375b68309beSRafal Kozik 3376b68309beSRafal Kozik if (!llq_features->max_llq_num) { 3377b68309beSRafal Kozik ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; 3378b68309beSRafal Kozik return 0; 3379b68309beSRafal Kozik } 3380b68309beSRafal Kozik 3381b68309beSRafal Kozik rc = ena_com_config_llq_info(ena_dev, llq_features, llq_default_cfg); 3382b68309beSRafal Kozik if (rc) 3383b68309beSRafal Kozik return rc; 3384b68309beSRafal Kozik 3385b2b02edeSMichal Krawczyk ena_dev->tx_max_header_size = llq_info->desc_list_entry_size - 3386b2b02edeSMichal Krawczyk (llq_info->descs_num_before_header * sizeof(struct ena_eth_io_tx_desc)); 3387b68309beSRafal Kozik 338841083bd5SMichal Krawczyk if (unlikely(ena_dev->tx_max_header_size == 0)) { 3389ac2fd8a5SMichal Krawczyk ena_trc_err(ena_dev, "The size of the LLQ entry is smaller than needed\n"); 3390f73f53f7SShai Brandes return ENA_COM_INVAL; 3391b68309beSRafal Kozik } 3392b68309beSRafal Kozik 3393b68309beSRafal Kozik ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_DEV; 3394b68309beSRafal Kozik 3395b68309beSRafal Kozik return 0; 3396b68309beSRafal Kozik } 3397