1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2019 Marvell International Ltd. 3 */ 4 5 #include <rte_memzone.h> 6 #include <rte_malloc.h> 7 8 #include "nitrox_qp.h" 9 #include "nitrox_hal.h" 10 #include "nitrox_logs.h" 11 12 #define MAX_CMD_QLEN 16384 13 #define CMDQ_PKT_IN_ALIGN 16 14 15 static int 16 nitrox_setup_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr, 17 const char *dev_name, uint8_t instr_size, int socket_id) 18 { 19 char mz_name[RTE_MEMZONE_NAMESIZE]; 20 const struct rte_memzone *mz; 21 size_t cmdq_size = qp->count * instr_size; 22 uint64_t offset; 23 int err = 0; 24 25 snprintf(mz_name, sizeof(mz_name), "%s_cmdq_%d", dev_name, qp->qno); 26 mz = rte_memzone_reserve_aligned(mz_name, cmdq_size, socket_id, 27 RTE_MEMZONE_SIZE_HINT_ONLY | 28 RTE_MEMZONE_256MB, 29 CMDQ_PKT_IN_ALIGN); 30 if (!mz) { 31 NITROX_LOG_LINE(ERR, "cmdq memzone reserve failed for %s queue", 32 mz_name); 33 return -ENOMEM; 34 } 35 36 switch (qp->type) { 37 case NITROX_QUEUE_SE: 38 offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(qp->qno); 39 qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset); 40 setup_nps_pkt_input_ring(bar_addr, qp->qno, qp->count, 41 mz->iova); 42 setup_nps_pkt_solicit_output_port(bar_addr, qp->qno); 43 break; 44 case NITROX_QUEUE_ZIP: 45 offset = ZQMQ_DRBLX(qp->qno); 46 qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset); 47 err = setup_zqmq_input_ring(bar_addr, qp->qno, qp->count, 48 mz->iova); 49 break; 50 default: 51 NITROX_LOG_LINE(ERR, "Invalid queue type %d", qp->type); 52 err = -EINVAL; 53 break; 54 } 55 56 if (err) { 57 rte_memzone_free(mz); 58 return err; 59 } 60 61 qp->cmdq.mz = mz; 62 qp->cmdq.ring = mz->addr; 63 qp->cmdq.instr_size = instr_size; 64 return 0; 65 } 66 67 static int 68 nitrox_setup_ridq(struct nitrox_qp *qp, int socket_id) 69 { 70 size_t ridq_size = qp->count * sizeof(*qp->ridq); 71 72 qp->ridq = rte_zmalloc_socket("nitrox ridq", ridq_size, 73 RTE_CACHE_LINE_SIZE, 74 socket_id); 75 if (!qp->ridq) { 76 NITROX_LOG_LINE(ERR, "Failed to create rid queue"); 77 return -ENOMEM; 78 } 79 80 return 0; 81 } 82 83 static int 84 nitrox_release_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr) 85 { 86 int err = 0; 87 88 switch (qp->type) { 89 case NITROX_QUEUE_SE: 90 nps_pkt_solicited_port_disable(bar_addr, qp->qno); 91 nps_pkt_input_ring_disable(bar_addr, qp->qno); 92 break; 93 case NITROX_QUEUE_ZIP: 94 err = zqmq_input_ring_disable(bar_addr, qp->qno); 95 break; 96 default: 97 err = -EINVAL; 98 } 99 100 if (err) 101 return err; 102 103 return rte_memzone_free(qp->cmdq.mz); 104 } 105 106 int 107 nitrox_qp_setup(struct nitrox_qp *qp, uint8_t *bar_addr, const char *dev_name, 108 uint32_t nb_descriptors, uint8_t instr_size, int socket_id) 109 { 110 int err; 111 uint32_t count; 112 113 count = rte_align32pow2(nb_descriptors); 114 if (count > MAX_CMD_QLEN) { 115 NITROX_LOG_LINE(ERR, "%s: Number of descriptors too big %d," 116 " greater than max queue length %d", 117 dev_name, count, 118 MAX_CMD_QLEN); 119 return -EINVAL; 120 } 121 122 qp->bar_addr = bar_addr; 123 qp->count = count; 124 qp->head = qp->tail = 0; 125 rte_atomic_store_explicit(&qp->pending_count, 0, 126 rte_memory_order_relaxed); 127 err = nitrox_setup_cmdq(qp, bar_addr, dev_name, instr_size, socket_id); 128 if (err) 129 return err; 130 131 err = nitrox_setup_ridq(qp, socket_id); 132 if (err) 133 goto ridq_err; 134 135 return 0; 136 137 ridq_err: 138 nitrox_release_cmdq(qp, bar_addr); 139 return err; 140 } 141 142 static void 143 nitrox_release_ridq(struct nitrox_qp *qp) 144 { 145 rte_free(qp->ridq); 146 } 147 148 int 149 nitrox_qp_release(struct nitrox_qp *qp, uint8_t *bar_addr) 150 { 151 nitrox_release_ridq(qp); 152 return nitrox_release_cmdq(qp, bar_addr); 153 } 154