Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2001-2023 Intel Corporation 3 : : */ 4 : : 5 : : 6 : : #include "idpf_controlq.h" 7 : : 8 : : 9 : : /** 10 : : * idpf_ctlq_alloc_desc_ring - Allocate Control Queue (CQ) rings 11 : : * @hw: pointer to hw struct 12 : : * @cq: pointer to the specific Control queue 13 : : */ 14 : : static int idpf_ctlq_alloc_desc_ring(struct idpf_hw *hw, 15 : : struct idpf_ctlq_info *cq) 16 : : { 17 : 0 : size_t size = cq->ring_size * sizeof(struct idpf_ctlq_desc); 18 : : 19 : 0 : cq->desc_ring.va = idpf_alloc_dma_mem(hw, &cq->desc_ring, size); 20 [ # # ]: 0 : if (!cq->desc_ring.va) 21 : : return -ENOMEM; 22 : : 23 : : return 0; 24 : : } 25 : : 26 : : /** 27 : : * idpf_ctlq_alloc_bufs - Allocate Control Queue (CQ) buffers 28 : : * @hw: pointer to hw struct 29 : : * @cq: pointer to the specific Control queue 30 : : * 31 : : * Allocate the buffer head for all control queues, and if it's a receive 32 : : * queue, allocate DMA buffers 33 : : */ 34 : 0 : static int idpf_ctlq_alloc_bufs(struct idpf_hw *hw, 35 : : struct idpf_ctlq_info *cq) 36 : : { 37 : : int i = 0; 38 : : 39 : : /* Do not allocate DMA buffers for transmit queues */ 40 [ # # ]: 0 : if (cq->cq_type == IDPF_CTLQ_TYPE_MAILBOX_TX) 41 : : return 0; 42 : : 43 : : /* We'll be allocating the buffer info memory first, then we can 44 : : * allocate the mapped buffers for the event processing 45 : : */ 46 : 0 : cq->bi.rx_buff = (struct idpf_dma_mem **) 47 : 0 : idpf_calloc(hw, cq->ring_size, 48 : : sizeof(struct idpf_dma_mem *)); 49 [ # # ]: 0 : if (!cq->bi.rx_buff) 50 : : return -ENOMEM; 51 : : 52 : : /* allocate the mapped buffers (except for the last one) */ 53 [ # # ]: 0 : for (i = 0; i < cq->ring_size - 1; i++) { 54 : : struct idpf_dma_mem *bi; 55 : : int num = 1; /* number of idpf_dma_mem to be allocated */ 56 : : 57 : 0 : cq->bi.rx_buff[i] = (struct idpf_dma_mem *)idpf_calloc(hw, num, 58 : : sizeof(struct idpf_dma_mem)); 59 [ # # ]: 0 : if (!cq->bi.rx_buff[i]) 60 : 0 : goto unwind_alloc_cq_bufs; 61 : : 62 : : bi = cq->bi.rx_buff[i]; 63 : : 64 : 0 : bi->va = idpf_alloc_dma_mem(hw, bi, cq->buf_size); 65 [ # # ]: 0 : if (!bi->va) { 66 : : /* unwind will not free the failed entry */ 67 : 0 : idpf_free(hw, cq->bi.rx_buff[i]); 68 : 0 : goto unwind_alloc_cq_bufs; 69 : : } 70 : : } 71 : : 72 : : return 0; 73 : : 74 : 0 : unwind_alloc_cq_bufs: 75 : : /* don't try to free the one that failed... */ 76 : 0 : i--; 77 [ # # ]: 0 : for (; i >= 0; i--) { 78 : 0 : idpf_free_dma_mem(hw, cq->bi.rx_buff[i]); 79 : 0 : idpf_free(hw, cq->bi.rx_buff[i]); 80 : : } 81 : 0 : idpf_free(hw, cq->bi.rx_buff); 82 : : 83 : 0 : return -ENOMEM; 84 : : } 85 : : 86 : : /** 87 : : * idpf_ctlq_free_desc_ring - Free Control Queue (CQ) rings 88 : : * @hw: pointer to hw struct 89 : : * @cq: pointer to the specific Control queue 90 : : * 91 : : * This assumes the posted send buffers have already been cleaned 92 : : * and de-allocated 93 : : */ 94 : : static void idpf_ctlq_free_desc_ring(struct idpf_hw *hw, 95 : : struct idpf_ctlq_info *cq) 96 : : { 97 : : idpf_free_dma_mem(hw, &cq->desc_ring); 98 : : } 99 : : 100 : : /** 101 : : * idpf_ctlq_free_bufs - Free CQ buffer info elements 102 : : * @hw: pointer to hw struct 103 : : * @cq: pointer to the specific Control queue 104 : : * 105 : : * Free the DMA buffers for RX queues, and DMA buffer header for both RX and TX 106 : : * queues. The upper layers are expected to manage freeing of TX DMA buffers 107 : : */ 108 : 0 : static void idpf_ctlq_free_bufs(struct idpf_hw *hw, struct idpf_ctlq_info *cq) 109 : : { 110 : : void *bi; 111 : : 112 [ # # ]: 0 : if (cq->cq_type == IDPF_CTLQ_TYPE_MAILBOX_RX) { 113 : : int i; 114 : : 115 : : /* free DMA buffers for rx queues*/ 116 [ # # ]: 0 : for (i = 0; i < cq->ring_size; i++) { 117 [ # # ]: 0 : if (cq->bi.rx_buff[i]) { 118 : : idpf_free_dma_mem(hw, cq->bi.rx_buff[i]); 119 : 0 : idpf_free(hw, cq->bi.rx_buff[i]); 120 : : } 121 : : } 122 : : 123 : 0 : bi = (void *)cq->bi.rx_buff; 124 : : } else { 125 : 0 : bi = (void *)cq->bi.tx_msg; 126 : : } 127 : : 128 : : /* free the buffer header */ 129 : 0 : idpf_free(hw, bi); 130 : 0 : } 131 : : 132 : : /** 133 : : * idpf_ctlq_dealloc_ring_res - Free memory allocated for control queue 134 : : * @hw: pointer to hw struct 135 : : * @cq: pointer to the specific Control queue 136 : : * 137 : : * Free the memory used by the ring, buffers and other related structures 138 : : */ 139 : 0 : void idpf_ctlq_dealloc_ring_res(struct idpf_hw *hw, struct idpf_ctlq_info *cq) 140 : : { 141 : : /* free ring buffers and the ring itself */ 142 : 0 : idpf_ctlq_free_bufs(hw, cq); 143 : : idpf_ctlq_free_desc_ring(hw, cq); 144 : 0 : } 145 : : 146 : : /** 147 : : * idpf_ctlq_alloc_ring_res - allocate memory for descriptor ring and bufs 148 : : * @hw: pointer to hw struct 149 : : * @cq: pointer to control queue struct 150 : : * 151 : : * Do *NOT* hold the lock when calling this as the memory allocation routines 152 : : * called are not going to be atomic context safe 153 : : */ 154 : 0 : int idpf_ctlq_alloc_ring_res(struct idpf_hw *hw, struct idpf_ctlq_info *cq) 155 : : { 156 : : int ret_code; 157 : : 158 : : /* verify input for valid configuration */ 159 [ # # # # ]: 0 : if (!cq->ring_size || !cq->buf_size) 160 : : return -EINVAL; 161 : : 162 : : /* allocate the ring memory */ 163 : : ret_code = idpf_ctlq_alloc_desc_ring(hw, cq); 164 : : if (ret_code) 165 : : return ret_code; 166 : : 167 : : /* allocate buffers in the rings */ 168 : 0 : ret_code = idpf_ctlq_alloc_bufs(hw, cq); 169 [ # # ]: 0 : if (ret_code) 170 : 0 : goto idpf_init_cq_free_ring; 171 : : 172 : : /* success! */ 173 : : return 0; 174 : : 175 : : idpf_init_cq_free_ring: 176 : : idpf_free_dma_mem(hw, &cq->desc_ring); 177 : 0 : return ret_code; 178 : : }