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 buff_pool->buf_elem[head++] = nbuf; 168 head &= (DP_RX_REFILL_BUFF_POOL_SIZE - 1); 169 count++; 170 } 171 172 if (count) { 173 buff_pool->head = head; 174 total_num_refill -= count; 175 total_count += count; 176 } 177 } 178 179 DP_STATS_INC(buff_pool->dp_pdev, 180 rx_refill_buff_pool.num_bufs_refilled, 181 total_count); 182 } 183 184 static inline qdf_nbuf_t dp_rx_refill_buff_pool_dequeue_nbuf(struct dp_soc *soc) 185 { 186 struct rx_refill_buff_pool *buff_pool = &soc->rx_refill_buff_pool; 187 qdf_nbuf_t nbuf = NULL; 188 uint16_t head, tail; 189 190 head = buff_pool->head; 191 tail = buff_pool->tail; 192 193 if (head == tail) 194 return NULL; 195 196 nbuf = buff_pool->buf_elem[tail++]; 197 tail &= (DP_RX_REFILL_BUFF_POOL_SIZE - 1); 198 buff_pool->tail = tail; 199 200 return nbuf; 201 } 202 203 qdf_nbuf_t 204 dp_rx_buffer_pool_nbuf_alloc(struct dp_soc *soc, uint32_t mac_id, 205 struct rx_desc_pool *rx_desc_pool, 206 uint32_t num_available_buffers) 207 { 208 struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); 209 struct rx_buff_pool *buff_pool; 210 struct dp_srng *dp_rxdma_srng; 211 qdf_nbuf_t nbuf; 212 213 nbuf = dp_rx_refill_buff_pool_dequeue_nbuf(soc); 214 if (qdf_likely(nbuf)) { 215 DP_STATS_INC(dp_pdev, 216 rx_refill_buff_pool.num_bufs_allocated, 1); 217 return nbuf; 218 } 219 220 if (!wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) 221 mac_id = dp_pdev->lmac_id; 222 223 buff_pool = &soc->rx_buff_pool[mac_id]; 224 dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id]; 225 226 nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 227 RX_BUFFER_RESERVATION, 228 rx_desc_pool->buf_alignment, 229 FALSE); 230 231 if (!buff_pool->is_initialized) 232 return nbuf; 233 234 if (qdf_likely(nbuf)) { 235 buff_pool->nbuf_fail_cnt = 0; 236 return nbuf; 237 } 238 239 buff_pool->nbuf_fail_cnt++; 240 241 /* Allocate buffer from the buffer pool */ 242 if (buff_pool->nbuf_fail_cnt >= DP_RX_BUFFER_POOL_ALLOC_THRES || 243 (num_available_buffers < dp_rxdma_srng->num_entries / 10)) { 244 nbuf = qdf_nbuf_queue_head_dequeue(&buff_pool->emerg_nbuf_q); 245 if (nbuf) 246 DP_STATS_INC(dp_pdev, 247 rx_buffer_pool.num_pool_bufs_replenish, 1); 248 } 249 250 return nbuf; 251 } 252 253 QDF_STATUS 254 dp_rx_buffer_pool_nbuf_map(struct dp_soc *soc, 255 struct rx_desc_pool *rx_desc_pool, 256 struct dp_rx_nbuf_frag_info *nbuf_frag_info_t) 257 { 258 QDF_STATUS ret = QDF_STATUS_SUCCESS; 259 260 if (!QDF_NBUF_CB_PADDR((nbuf_frag_info_t->virt_addr).nbuf)) 261 ret = qdf_nbuf_map_nbytes_single(soc->osdev, 262 (nbuf_frag_info_t->virt_addr).nbuf, 263 QDF_DMA_FROM_DEVICE, 264 rx_desc_pool->buf_size); 265 266 return ret; 267 } 268 269 static void dp_rx_refill_buff_pool_init(struct dp_soc *soc, u8 mac_id) 270 { 271 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 272 qdf_nbuf_t nbuf; 273 struct rx_refill_buff_pool *buff_pool = &soc->rx_refill_buff_pool; 274 QDF_STATUS ret; 275 uint16_t head = 0; 276 int i; 277 278 if (!wlan_cfg_is_rx_refill_buffer_pool_enabled(soc->wlan_cfg_ctx)) { 279 dp_err("RX refill buffer pool support is disabled"); 280 buff_pool->is_initialized = false; 281 return; 282 } 283 284 buff_pool->max_bufq_len = DP_RX_REFILL_BUFF_POOL_SIZE; 285 buff_pool->dp_pdev = dp_get_pdev_for_lmac_id(soc, 0); 286 buff_pool->tail = 0; 287 288 for (i = 0; i < (buff_pool->max_bufq_len - 1); i++) { 289 nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 290 RX_BUFFER_RESERVATION, 291 rx_desc_pool->buf_alignment, FALSE); 292 if (!nbuf) 293 continue; 294 295 ret = qdf_nbuf_map_nbytes_single(soc->osdev, nbuf, 296 QDF_DMA_FROM_DEVICE, 297 rx_desc_pool->buf_size); 298 if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) { 299 qdf_nbuf_free(nbuf); 300 continue; 301 } 302 303 buff_pool->buf_elem[head] = nbuf; 304 head++; 305 } 306 307 buff_pool->head = head; 308 309 dp_info("RX refill buffer pool required allocation: %u actual allocation: %u", 310 buff_pool->max_bufq_len, 311 buff_pool->head); 312 313 buff_pool->is_initialized = true; 314 } 315 316 void dp_rx_buffer_pool_init(struct dp_soc *soc, u8 mac_id) 317 { 318 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 319 struct rx_buff_pool *buff_pool = &soc->rx_buff_pool[mac_id]; 320 qdf_nbuf_t nbuf; 321 int i; 322 323 dp_rx_refill_buff_pool_init(soc, mac_id); 324 325 if (!wlan_cfg_is_rx_buffer_pool_enabled(soc->wlan_cfg_ctx)) { 326 dp_err("RX buffer pool support is disabled"); 327 buff_pool->is_initialized = false; 328 return; 329 } 330 331 if (buff_pool->is_initialized) 332 return; 333 334 qdf_nbuf_queue_head_init(&buff_pool->emerg_nbuf_q); 335 336 for (i = 0; i < DP_RX_BUFFER_POOL_SIZE; i++) { 337 nbuf = qdf_nbuf_alloc(soc->osdev, rx_desc_pool->buf_size, 338 RX_BUFFER_RESERVATION, 339 rx_desc_pool->buf_alignment, FALSE); 340 if (!nbuf) 341 continue; 342 qdf_nbuf_queue_head_enqueue_tail(&buff_pool->emerg_nbuf_q, 343 nbuf); 344 } 345 346 dp_info("RX buffer pool required allocation: %u actual allocation: %u", 347 DP_RX_BUFFER_POOL_SIZE, 348 qdf_nbuf_queue_head_qlen(&buff_pool->emerg_nbuf_q)); 349 350 buff_pool->is_initialized = true; 351 } 352 353 static void dp_rx_refill_buff_pool_deinit(struct dp_soc *soc, u8 mac_id) 354 { 355 struct rx_refill_buff_pool *buff_pool = &soc->rx_refill_buff_pool; 356 struct rx_desc_pool *rx_desc_pool = &soc->rx_desc_buf[mac_id]; 357 qdf_nbuf_t nbuf; 358 uint32_t count = 0; 359 360 if (!buff_pool->is_initialized) 361 return; 362 363 while ((nbuf = dp_rx_refill_buff_pool_dequeue_nbuf(soc))) { 364 qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, 365 QDF_DMA_BIDIRECTIONAL, 366 rx_desc_pool->buf_size); 367 qdf_nbuf_free(nbuf); 368 count++; 369 } 370 371 dp_info("Rx refill buffers freed during deinit %u head: %u, tail: %u", 372 count, buff_pool->head, buff_pool->tail); 373 374 buff_pool->is_initialized = false; 375 } 376 377 void dp_rx_buffer_pool_deinit(struct dp_soc *soc, u8 mac_id) 378 { 379 struct rx_buff_pool *buff_pool = &soc->rx_buff_pool[mac_id]; 380 qdf_nbuf_t nbuf; 381 382 dp_rx_refill_buff_pool_deinit(soc, mac_id); 383 384 if (!buff_pool->is_initialized) 385 return; 386 387 dp_info("buffers in the RX buffer pool during deinit: %u", 388 qdf_nbuf_queue_head_qlen(&buff_pool->emerg_nbuf_q)); 389 390 while ((nbuf = qdf_nbuf_queue_head_dequeue(&buff_pool->emerg_nbuf_q))) 391 qdf_nbuf_free(nbuf); 392 393 buff_pool->is_initialized = false; 394 } 395 #endif /* WLAN_FEATURE_RX_PREALLOC_BUFFER_POOL */ 396