1 /* 2 * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include "dp_rx_buffer_pool.h" 21 #include "dp_ipa.h" 22 23 #ifndef DP_RX_BUFFER_POOL_SIZE 24 #define DP_RX_BUFFER_POOL_SIZE 128 25 #endif 26 27 #ifndef DP_RX_BUFF_POOL_ALLOC_THRES 28 #define DP_RX_BUFF_POOL_ALLOC_THRES 1 29 #endif 30 31 #ifdef WLAN_FEATURE_RX_PREALLOC_BUFFER_POOL 32 bool dp_rx_buffer_pool_refill(struct dp_soc *soc, qdf_nbuf_t nbuf, u8 mac_id) 33 { 34 struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); 35 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 36 struct rx_buff_pool *bufpool = &soc->rx_buff_pool[mac_id]; 37 qdf_nbuf_t next_nbuf, first_nbuf, refill_nbuf; 38 bool consumed = false; 39 40 if (!bufpool->is_initialized || !pdev) 41 return consumed; 42 43 /* process only buffers of RXDMA ring */ 44 if (soc->wlan_cfg_ctx->rxdma1_enable) 45 return consumed; 46 47 first_nbuf = nbuf; 48 49 while (nbuf) { 50 next_nbuf = qdf_nbuf_next(nbuf); 51 52 if (qdf_likely(qdf_nbuf_queue_head_qlen(&bufpool->emerg_nbuf_q) >= 53 DP_RX_BUFFER_POOL_SIZE)) 54 break; 55 56 refill_nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 57 RX_BUFFER_RESERVATION, 58 rx_desc_pool->buf_alignment, 59 FALSE); 60 61 /* Failed to allocate new nbuf, reset and place it back 62 * in to the pool. 63 */ 64 if (!refill_nbuf) { 65 DP_STATS_INC(pdev, 66 rx_buffer_pool.num_bufs_consumed, 1); 67 consumed = true; 68 break; 69 } 70 71 /* Successful allocation!! */ 72 DP_STATS_INC(pdev, 73 rx_buffer_pool.num_bufs_alloc_success, 1); 74 qdf_nbuf_queue_head_enqueue_tail(&bufpool->emerg_nbuf_q, 75 refill_nbuf); 76 nbuf = next_nbuf; 77 } 78 79 nbuf = first_nbuf; 80 if (consumed) { 81 /* Free the MSDU/scattered MSDU */ 82 while (nbuf) { 83 next_nbuf = qdf_nbuf_next(nbuf); 84 dp_rx_buffer_pool_nbuf_free(soc, nbuf, mac_id); 85 nbuf = next_nbuf; 86 } 87 } 88 89 return consumed; 90 } 91 92 void dp_rx_buffer_pool_nbuf_free(struct dp_soc *soc, qdf_nbuf_t nbuf, u8 mac_id) 93 { 94 struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); 95 struct rx_desc_pool *rx_desc_pool; 96 struct rx_buff_pool *buff_pool; 97 98 if (!wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) 99 mac_id = dp_pdev->lmac_id; 100 101 rx_desc_pool = &soc->rx_desc_buf[mac_id]; 102 buff_pool = &soc->rx_buff_pool[mac_id]; 103 104 if (qdf_likely(qdf_nbuf_queue_head_qlen(&buff_pool->emerg_nbuf_q) >= 105 DP_RX_BUFFER_POOL_SIZE) || 106 !buff_pool->is_initialized) 107 return qdf_nbuf_free(nbuf); 108 109 qdf_nbuf_reset(nbuf, RX_BUFFER_RESERVATION, 110 rx_desc_pool->buf_alignment); 111 qdf_nbuf_queue_head_enqueue_tail(&buff_pool->emerg_nbuf_q, nbuf); 112 } 113 114 void dp_rx_refill_buff_pool_enqueue(struct dp_soc *soc) 115 { 116 struct rx_desc_pool *rx_desc_pool; 117 struct rx_refill_buff_pool *buff_pool; 118 qdf_device_t dev; 119 qdf_nbuf_t nbuf; 120 QDF_STATUS ret; 121 int count, i; 122 uint16_t num_refill; 123 uint16_t total_num_refill; 124 uint16_t total_count = 0; 125 uint16_t head, tail; 126 127 if (!soc) 128 return; 129 130 dev = soc->osdev; 131 buff_pool = &soc->rx_refill_buff_pool; 132 rx_desc_pool = &soc->rx_desc_buf[0]; 133 if (!buff_pool->is_initialized) 134 return; 135 136 head = buff_pool->head; 137 tail = buff_pool->tail; 138 if (tail > head) 139 total_num_refill = (tail - head - 1); 140 else 141 total_num_refill = (DP_RX_REFILL_BUFF_POOL_SIZE - head + 142 tail - 1); 143 144 while (total_num_refill) { 145 if (total_num_refill > DP_RX_REFILL_BUFF_POOL_BURST) 146 num_refill = DP_RX_REFILL_BUFF_POOL_BURST; 147 else 148 num_refill = total_num_refill; 149 150 count = 0; 151 for (i = 0; i < num_refill; i++) { 152 nbuf = qdf_nbuf_alloc(dev, rx_desc_pool->buf_size, 153 RX_BUFFER_RESERVATION, 154 rx_desc_pool->buf_alignment, 155 FALSE); 156 if (qdf_unlikely(!nbuf)) 157 continue; 158 159 ret = qdf_nbuf_map_nbytes_single(dev, nbuf, 160 QDF_DMA_FROM_DEVICE, 161 rx_desc_pool->buf_size); 162 if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) { 163 qdf_nbuf_free(nbuf); 164 continue; 165 } 166 167 dp_audio_smmu_map(dev, 168 qdf_mem_paddr_from_dmaaddr(dev, 169 QDF_NBUF_CB_PADDR(nbuf)), 170 QDF_NBUF_CB_PADDR(nbuf), 171 rx_desc_pool->buf_size); 172 173 buff_pool->buf_elem[head++] = nbuf; 174 head &= (DP_RX_REFILL_BUFF_POOL_SIZE - 1); 175 count++; 176 } 177 178 if (count) { 179 buff_pool->head = head; 180 total_num_refill -= count; 181 total_count += count; 182 } 183 } 184 185 DP_STATS_INC(buff_pool->dp_pdev, 186 rx_refill_buff_pool.num_bufs_refilled, 187 total_count); 188 } 189 190 static inline qdf_nbuf_t dp_rx_refill_buff_pool_dequeue_nbuf(struct dp_soc *soc) 191 { 192 struct rx_refill_buff_pool *buff_pool = &soc->rx_refill_buff_pool; 193 qdf_nbuf_t nbuf = NULL; 194 uint16_t head, tail; 195 196 head = buff_pool->head; 197 tail = buff_pool->tail; 198 199 if (head == tail) 200 return NULL; 201 202 nbuf = buff_pool->buf_elem[tail++]; 203 tail &= (DP_RX_REFILL_BUFF_POOL_SIZE - 1); 204 buff_pool->tail = tail; 205 206 return nbuf; 207 } 208 209 qdf_nbuf_t 210 dp_rx_buffer_pool_nbuf_alloc(struct dp_soc *soc, uint32_t mac_id, 211 struct rx_desc_pool *rx_desc_pool, 212 uint32_t num_available_buffers) 213 { 214 struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); 215 struct rx_buff_pool *buff_pool; 216 struct dp_srng *dp_rxdma_srng; 217 qdf_nbuf_t nbuf; 218 219 nbuf = dp_rx_refill_buff_pool_dequeue_nbuf(soc); 220 if (qdf_likely(nbuf)) { 221 DP_STATS_INC(dp_pdev, 222 rx_refill_buff_pool.num_bufs_allocated, 1); 223 return nbuf; 224 } 225 226 if (!wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) 227 mac_id = dp_pdev->lmac_id; 228 229 buff_pool = &soc->rx_buff_pool[mac_id]; 230 dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id]; 231 232 nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 233 RX_BUFFER_RESERVATION, 234 rx_desc_pool->buf_alignment, 235 FALSE); 236 237 if (!buff_pool->is_initialized) 238 return nbuf; 239 240 if (qdf_likely(nbuf)) { 241 buff_pool->nbuf_fail_cnt = 0; 242 return nbuf; 243 } 244 245 buff_pool->nbuf_fail_cnt++; 246 247 /* Allocate buffer from the buffer pool */ 248 if (buff_pool->nbuf_fail_cnt >= DP_RX_BUFFER_POOL_ALLOC_THRES || 249 (num_available_buffers < dp_rxdma_srng->num_entries / 10)) { 250 nbuf = qdf_nbuf_queue_head_dequeue(&buff_pool->emerg_nbuf_q); 251 if (nbuf) 252 DP_STATS_INC(dp_pdev, 253 rx_buffer_pool.num_pool_bufs_replenish, 1); 254 } 255 256 return nbuf; 257 } 258 259 QDF_STATUS 260 dp_rx_buffer_pool_nbuf_map(struct dp_soc *soc, 261 struct rx_desc_pool *rx_desc_pool, 262 struct dp_rx_nbuf_frag_info *nbuf_frag_info_t) 263 { 264 QDF_STATUS ret = QDF_STATUS_SUCCESS; 265 266 if (!QDF_NBUF_CB_PADDR((nbuf_frag_info_t->virt_addr).nbuf)) { 267 ret = qdf_nbuf_map_nbytes_single(soc->osdev, 268 (nbuf_frag_info_t->virt_addr).nbuf, 269 QDF_DMA_FROM_DEVICE, 270 rx_desc_pool->buf_size); 271 if (QDF_IS_STATUS_SUCCESS(ret)) 272 dp_audio_smmu_map(soc->osdev, 273 qdf_mem_paddr_from_dmaaddr(soc->osdev, 274 QDF_NBUF_CB_PADDR((nbuf_frag_info_t->virt_addr).nbuf)), 275 QDF_NBUF_CB_PADDR((nbuf_frag_info_t->virt_addr).nbuf), 276 rx_desc_pool->buf_size); 277 } 278 279 280 return ret; 281 } 282 283 static void dp_rx_refill_buff_pool_init(struct dp_soc *soc, u8 mac_id) 284 { 285 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 286 qdf_nbuf_t nbuf; 287 struct rx_refill_buff_pool *buff_pool = &soc->rx_refill_buff_pool; 288 QDF_STATUS ret; 289 uint16_t head = 0; 290 int i; 291 292 if (!wlan_cfg_is_rx_refill_buffer_pool_enabled(soc->wlan_cfg_ctx)) { 293 dp_err("RX refill buffer pool support is disabled"); 294 buff_pool->is_initialized = false; 295 return; 296 } 297 298 buff_pool->max_bufq_len = DP_RX_REFILL_BUFF_POOL_SIZE; 299 buff_pool->dp_pdev = dp_get_pdev_for_lmac_id(soc, 0); 300 buff_pool->tail = 0; 301 302 for (i = 0; i < (buff_pool->max_bufq_len - 1); i++) { 303 nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 304 RX_BUFFER_RESERVATION, 305 rx_desc_pool->buf_alignment, FALSE); 306 if (!nbuf) 307 continue; 308 309 ret = qdf_nbuf_map_nbytes_single(soc->osdev, nbuf, 310 QDF_DMA_FROM_DEVICE, 311 rx_desc_pool->buf_size); 312 if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) { 313 qdf_nbuf_free(nbuf); 314 continue; 315 } 316 317 dp_audio_smmu_map(soc->osdev, 318 qdf_mem_paddr_from_dmaaddr(soc->osdev, 319 QDF_NBUF_CB_PADDR(nbuf)), 320 QDF_NBUF_CB_PADDR(nbuf), 321 rx_desc_pool->buf_size); 322 323 buff_pool->buf_elem[head] = nbuf; 324 head++; 325 } 326 327 buff_pool->head = head; 328 329 dp_info("RX refill buffer pool required allocation: %u actual allocation: %u", 330 buff_pool->max_bufq_len, 331 buff_pool->head); 332 333 buff_pool->is_initialized = true; 334 } 335 336 void dp_rx_buffer_pool_init(struct dp_soc *soc, u8 mac_id) 337 { 338 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 339 struct rx_buff_pool *buff_pool = &soc->rx_buff_pool[mac_id]; 340 qdf_nbuf_t nbuf; 341 int i; 342 343 dp_rx_refill_buff_pool_init(soc, mac_id); 344 345 if (!wlan_cfg_is_rx_buffer_pool_enabled(soc->wlan_cfg_ctx)) { 346 dp_err("RX buffer pool support is disabled"); 347 buff_pool->is_initialized = false; 348 return; 349 } 350 351 if (buff_pool->is_initialized) 352 return; 353 354 qdf_nbuf_queue_head_init(&buff_pool->emerg_nbuf_q); 355 356 for (i = 0; i < DP_RX_BUFFER_POOL_SIZE; i++) { 357 nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 358 RX_BUFFER_RESERVATION, 359 rx_desc_pool->buf_alignment, FALSE); 360 if (!nbuf) 361 continue; 362 qdf_nbuf_queue_head_enqueue_tail(&buff_pool->emerg_nbuf_q, 363 nbuf); 364 } 365 366 dp_info("RX buffer pool required allocation: %u actual allocation: %u", 367 DP_RX_BUFFER_POOL_SIZE, 368 qdf_nbuf_queue_head_qlen(&buff_pool->emerg_nbuf_q)); 369 370 buff_pool->is_initialized = true; 371 } 372 373 static void dp_rx_refill_buff_pool_deinit(struct dp_soc *soc, u8 mac_id) 374 { 375 struct rx_refill_buff_pool *buff_pool = &soc->rx_refill_buff_pool; 376 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 377 qdf_nbuf_t nbuf; 378 uint32_t count = 0; 379 380 if (!buff_pool->is_initialized) 381 return; 382 383 while ((nbuf = dp_rx_refill_buff_pool_dequeue_nbuf(soc))) { 384 dp_audio_smmu_unmap(soc->osdev, 385 QDF_NBUF_CB_PADDR(nbuf), 386 rx_desc_pool->buf_size); 387 qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, 388 QDF_DMA_BIDIRECTIONAL, 389 rx_desc_pool->buf_size); 390 qdf_nbuf_free(nbuf); 391 count++; 392 } 393 394 dp_info("Rx refill buffers freed during deinit %u head: %u, tail: %u", 395 count, buff_pool->head, buff_pool->tail); 396 397 buff_pool->is_initialized = false; 398 } 399 400 void dp_rx_buffer_pool_deinit(struct dp_soc *soc, u8 mac_id) 401 { 402 struct rx_buff_pool *buff_pool = &soc->rx_buff_pool[mac_id]; 403 qdf_nbuf_t nbuf; 404 405 dp_rx_refill_buff_pool_deinit(soc, mac_id); 406 407 if (!buff_pool->is_initialized) 408 return; 409 410 dp_info("buffers in the RX buffer pool during deinit: %u", 411 qdf_nbuf_queue_head_qlen(&buff_pool->emerg_nbuf_q)); 412 413 while ((nbuf = qdf_nbuf_queue_head_dequeue(&buff_pool->emerg_nbuf_q))) 414 qdf_nbuf_free(nbuf); 415 416 buff_pool->is_initialized = false; 417 } 418 #endif /* WLAN_FEATURE_RX_PREALLOC_BUFFER_POOL */ 419