18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause-Clear 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "core.h" 78c2ecf20Sopenharmony_ci#include "debug.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_cistatic int ath11k_dbring_bufs_replenish(struct ath11k *ar, 108c2ecf20Sopenharmony_ci struct ath11k_dbring *ring, 118c2ecf20Sopenharmony_ci struct ath11k_dbring_element *buff) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci struct ath11k_base *ab = ar->ab; 148c2ecf20Sopenharmony_ci struct hal_srng *srng; 158c2ecf20Sopenharmony_ci dma_addr_t paddr; 168c2ecf20Sopenharmony_ci void *ptr_aligned, *ptr_unaligned, *desc; 178c2ecf20Sopenharmony_ci int ret; 188c2ecf20Sopenharmony_ci int buf_id; 198c2ecf20Sopenharmony_ci u32 cookie; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci srng = &ab->hal.srng_list[ring->refill_srng.ring_id]; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci lockdep_assert_held(&srng->lock); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci ath11k_hal_srng_access_begin(ab, srng); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci ptr_unaligned = buff->payload; 288c2ecf20Sopenharmony_ci ptr_aligned = PTR_ALIGN(ptr_unaligned, ring->buf_align); 298c2ecf20Sopenharmony_ci paddr = dma_map_single(ab->dev, ptr_aligned, ring->buf_sz, 308c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci ret = dma_mapping_error(ab->dev, paddr); 338c2ecf20Sopenharmony_ci if (ret) 348c2ecf20Sopenharmony_ci goto err; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci spin_lock_bh(&ring->idr_lock); 378c2ecf20Sopenharmony_ci buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, GFP_ATOMIC); 388c2ecf20Sopenharmony_ci spin_unlock_bh(&ring->idr_lock); 398c2ecf20Sopenharmony_ci if (buf_id < 0) { 408c2ecf20Sopenharmony_ci ret = -ENOBUFS; 418c2ecf20Sopenharmony_ci goto err_dma_unmap; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci desc = ath11k_hal_srng_src_get_next_entry(ab, srng); 458c2ecf20Sopenharmony_ci if (!desc) { 468c2ecf20Sopenharmony_ci ret = -ENOENT; 478c2ecf20Sopenharmony_ci goto err_idr_remove; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci buff->paddr = paddr; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, ar->pdev_idx) | 538c2ecf20Sopenharmony_ci FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci ath11k_hal_srng_access_end(ab, srng); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci return 0; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cierr_idr_remove: 628c2ecf20Sopenharmony_ci spin_lock_bh(&ring->idr_lock); 638c2ecf20Sopenharmony_ci idr_remove(&ring->bufs_idr, buf_id); 648c2ecf20Sopenharmony_ci spin_unlock_bh(&ring->idr_lock); 658c2ecf20Sopenharmony_cierr_dma_unmap: 668c2ecf20Sopenharmony_ci dma_unmap_single(ab->dev, paddr, ring->buf_sz, 678c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 688c2ecf20Sopenharmony_cierr: 698c2ecf20Sopenharmony_ci ath11k_hal_srng_access_end(ab, srng); 708c2ecf20Sopenharmony_ci return ret; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic int ath11k_dbring_fill_bufs(struct ath11k *ar, 748c2ecf20Sopenharmony_ci struct ath11k_dbring *ring) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct ath11k_dbring_element *buff; 778c2ecf20Sopenharmony_ci struct hal_srng *srng; 788c2ecf20Sopenharmony_ci int num_remain, req_entries, num_free; 798c2ecf20Sopenharmony_ci u32 align; 808c2ecf20Sopenharmony_ci int size, ret; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci srng = &ar->ab->hal.srng_list[ring->refill_srng.ring_id]; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci spin_lock_bh(&srng->lock); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci num_free = ath11k_hal_srng_src_num_free(ar->ab, srng, true); 878c2ecf20Sopenharmony_ci req_entries = min(num_free, ring->bufs_max); 888c2ecf20Sopenharmony_ci num_remain = req_entries; 898c2ecf20Sopenharmony_ci align = ring->buf_align; 908c2ecf20Sopenharmony_ci size = sizeof(*buff) + ring->buf_sz + align - 1; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci while (num_remain > 0) { 938c2ecf20Sopenharmony_ci buff = kzalloc(size, GFP_ATOMIC); 948c2ecf20Sopenharmony_ci if (!buff) 958c2ecf20Sopenharmony_ci break; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci ret = ath11k_dbring_bufs_replenish(ar, ring, buff); 988c2ecf20Sopenharmony_ci if (ret) { 998c2ecf20Sopenharmony_ci ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n", 1008c2ecf20Sopenharmony_ci num_remain, req_entries); 1018c2ecf20Sopenharmony_ci kfree(buff); 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci num_remain--; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci spin_unlock_bh(&srng->lock); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return num_remain; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciint ath11k_dbring_wmi_cfg_setup(struct ath11k *ar, 1138c2ecf20Sopenharmony_ci struct ath11k_dbring *ring, 1148c2ecf20Sopenharmony_ci enum wmi_direct_buffer_module id) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct ath11k_wmi_pdev_dma_ring_cfg_req_cmd param = {0}; 1178c2ecf20Sopenharmony_ci int ret; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (id >= WMI_DIRECT_BUF_MAX) 1208c2ecf20Sopenharmony_ci return -EINVAL; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci param.pdev_id = DP_SW2HW_MACID(ring->pdev_id); 1238c2ecf20Sopenharmony_ci param.module_id = id; 1248c2ecf20Sopenharmony_ci param.base_paddr_lo = lower_32_bits(ring->refill_srng.paddr); 1258c2ecf20Sopenharmony_ci param.base_paddr_hi = upper_32_bits(ring->refill_srng.paddr); 1268c2ecf20Sopenharmony_ci param.head_idx_paddr_lo = lower_32_bits(ring->hp_addr); 1278c2ecf20Sopenharmony_ci param.head_idx_paddr_hi = upper_32_bits(ring->hp_addr); 1288c2ecf20Sopenharmony_ci param.tail_idx_paddr_lo = lower_32_bits(ring->tp_addr); 1298c2ecf20Sopenharmony_ci param.tail_idx_paddr_hi = upper_32_bits(ring->tp_addr); 1308c2ecf20Sopenharmony_ci param.num_elems = ring->bufs_max; 1318c2ecf20Sopenharmony_ci param.buf_size = ring->buf_sz; 1328c2ecf20Sopenharmony_ci param.num_resp_per_event = ring->num_resp_per_event; 1338c2ecf20Sopenharmony_ci param.event_timeout_ms = ring->event_timeout_ms; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci ret = ath11k_wmi_pdev_dma_ring_cfg(ar, ¶m); 1368c2ecf20Sopenharmony_ci if (ret) { 1378c2ecf20Sopenharmony_ci ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); 1388c2ecf20Sopenharmony_ci return ret; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ciint ath11k_dbring_set_cfg(struct ath11k *ar, struct ath11k_dbring *ring, 1458c2ecf20Sopenharmony_ci u32 num_resp_per_event, u32 event_timeout_ms, 1468c2ecf20Sopenharmony_ci int (*handler)(struct ath11k *, 1478c2ecf20Sopenharmony_ci struct ath11k_dbring_data *)) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci if (WARN_ON(!ring)) 1508c2ecf20Sopenharmony_ci return -EINVAL; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci ring->num_resp_per_event = num_resp_per_event; 1538c2ecf20Sopenharmony_ci ring->event_timeout_ms = event_timeout_ms; 1548c2ecf20Sopenharmony_ci ring->handler = handler; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ciint ath11k_dbring_buf_setup(struct ath11k *ar, 1608c2ecf20Sopenharmony_ci struct ath11k_dbring *ring, 1618c2ecf20Sopenharmony_ci struct ath11k_dbring_cap *db_cap) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct ath11k_base *ab = ar->ab; 1648c2ecf20Sopenharmony_ci struct hal_srng *srng; 1658c2ecf20Sopenharmony_ci int ret; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci srng = &ab->hal.srng_list[ring->refill_srng.ring_id]; 1688c2ecf20Sopenharmony_ci ring->bufs_max = ring->refill_srng.size / 1698c2ecf20Sopenharmony_ci ath11k_hal_srng_get_entrysize(ab, HAL_RXDMA_DIR_BUF); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci ring->buf_sz = db_cap->min_buf_sz; 1728c2ecf20Sopenharmony_ci ring->buf_align = db_cap->min_buf_align; 1738c2ecf20Sopenharmony_ci ring->pdev_id = db_cap->pdev_id; 1748c2ecf20Sopenharmony_ci ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng); 1758c2ecf20Sopenharmony_ci ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci ret = ath11k_dbring_fill_bufs(ar, ring); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return ret; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciint ath11k_dbring_srng_setup(struct ath11k *ar, struct ath11k_dbring *ring, 1838c2ecf20Sopenharmony_ci int ring_num, int num_entries) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci int ret; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci ret = ath11k_dp_srng_setup(ar->ab, &ring->refill_srng, HAL_RXDMA_DIR_BUF, 1888c2ecf20Sopenharmony_ci ring_num, ar->pdev_idx, num_entries); 1898c2ecf20Sopenharmony_ci if (ret < 0) { 1908c2ecf20Sopenharmony_ci ath11k_warn(ar->ab, "failed to setup srng: %d ring_id %d\n", 1918c2ecf20Sopenharmony_ci ret, ring_num); 1928c2ecf20Sopenharmony_ci goto err; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci return 0; 1968c2ecf20Sopenharmony_cierr: 1978c2ecf20Sopenharmony_ci ath11k_dp_srng_cleanup(ar->ab, &ring->refill_srng); 1988c2ecf20Sopenharmony_ci return ret; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ciint ath11k_dbring_get_cap(struct ath11k_base *ab, 2028c2ecf20Sopenharmony_ci u8 pdev_idx, 2038c2ecf20Sopenharmony_ci enum wmi_direct_buffer_module id, 2048c2ecf20Sopenharmony_ci struct ath11k_dbring_cap *db_cap) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci int i; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (!ab->num_db_cap || !ab->db_caps) 2098c2ecf20Sopenharmony_ci return -ENOENT; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (id >= WMI_DIRECT_BUF_MAX) 2128c2ecf20Sopenharmony_ci return -EINVAL; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci for (i = 0; i < ab->num_db_cap; i++) { 2158c2ecf20Sopenharmony_ci if (pdev_idx == ab->db_caps[i].pdev_id && 2168c2ecf20Sopenharmony_ci id == ab->db_caps[i].id) { 2178c2ecf20Sopenharmony_ci *db_cap = ab->db_caps[i]; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci return 0; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci return -ENOENT; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ciint ath11k_dbring_buffer_release_event(struct ath11k_base *ab, 2278c2ecf20Sopenharmony_ci struct ath11k_dbring_buf_release_event *ev) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct ath11k_dbring *ring; 2308c2ecf20Sopenharmony_ci struct hal_srng *srng; 2318c2ecf20Sopenharmony_ci struct ath11k *ar; 2328c2ecf20Sopenharmony_ci struct ath11k_dbring_element *buff; 2338c2ecf20Sopenharmony_ci struct ath11k_dbring_data handler_data; 2348c2ecf20Sopenharmony_ci struct ath11k_buffer_addr desc; 2358c2ecf20Sopenharmony_ci u8 *vaddr_unalign; 2368c2ecf20Sopenharmony_ci u32 num_entry, num_buff_reaped; 2378c2ecf20Sopenharmony_ci u8 pdev_idx, rbm; 2388c2ecf20Sopenharmony_ci u32 cookie; 2398c2ecf20Sopenharmony_ci int buf_id; 2408c2ecf20Sopenharmony_ci int size; 2418c2ecf20Sopenharmony_ci dma_addr_t paddr; 2428c2ecf20Sopenharmony_ci int ret = 0; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci pdev_idx = ev->fixed.pdev_id; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (pdev_idx >= ab->num_radios) { 2478c2ecf20Sopenharmony_ci ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx); 2488c2ecf20Sopenharmony_ci return -EINVAL; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (ev->fixed.num_buf_release_entry != 2528c2ecf20Sopenharmony_ci ev->fixed.num_meta_data_entry) { 2538c2ecf20Sopenharmony_ci ath11k_warn(ab, "Buffer entry %d mismatch meta entry %d\n", 2548c2ecf20Sopenharmony_ci ev->fixed.num_buf_release_entry, 2558c2ecf20Sopenharmony_ci ev->fixed.num_meta_data_entry); 2568c2ecf20Sopenharmony_ci return -EINVAL; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci ar = ab->pdevs[pdev_idx].ar; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci rcu_read_lock(); 2628c2ecf20Sopenharmony_ci if (!rcu_dereference(ab->pdevs_active[pdev_idx])) { 2638c2ecf20Sopenharmony_ci ret = -EINVAL; 2648c2ecf20Sopenharmony_ci goto rcu_unlock; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci switch (ev->fixed.module_id) { 2688c2ecf20Sopenharmony_ci case WMI_DIRECT_BUF_SPECTRAL: 2698c2ecf20Sopenharmony_ci ring = ath11k_spectral_get_dbring(ar); 2708c2ecf20Sopenharmony_ci break; 2718c2ecf20Sopenharmony_ci default: 2728c2ecf20Sopenharmony_ci ring = NULL; 2738c2ecf20Sopenharmony_ci ath11k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n", 2748c2ecf20Sopenharmony_ci ev->fixed.module_id); 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (!ring) { 2798c2ecf20Sopenharmony_ci ret = -EINVAL; 2808c2ecf20Sopenharmony_ci goto rcu_unlock; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci srng = &ab->hal.srng_list[ring->refill_srng.ring_id]; 2848c2ecf20Sopenharmony_ci num_entry = ev->fixed.num_buf_release_entry; 2858c2ecf20Sopenharmony_ci size = sizeof(*buff) + ring->buf_sz + ring->buf_align - 1; 2868c2ecf20Sopenharmony_ci num_buff_reaped = 0; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci spin_lock_bh(&srng->lock); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci while (num_buff_reaped < num_entry) { 2918c2ecf20Sopenharmony_ci desc.info0 = ev->buf_entry[num_buff_reaped].paddr_lo; 2928c2ecf20Sopenharmony_ci desc.info1 = ev->buf_entry[num_buff_reaped].paddr_hi; 2938c2ecf20Sopenharmony_ci handler_data.meta = ev->meta_data[num_buff_reaped]; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci num_buff_reaped++; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci ath11k_hal_rx_buf_addr_info_get(&desc, &paddr, &cookie, &rbm); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, cookie); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci spin_lock_bh(&ring->idr_lock); 3028c2ecf20Sopenharmony_ci buff = idr_find(&ring->bufs_idr, buf_id); 3038c2ecf20Sopenharmony_ci if (!buff) { 3048c2ecf20Sopenharmony_ci spin_unlock_bh(&ring->idr_lock); 3058c2ecf20Sopenharmony_ci continue; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci idr_remove(&ring->bufs_idr, buf_id); 3088c2ecf20Sopenharmony_ci spin_unlock_bh(&ring->idr_lock); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci dma_unmap_single(ab->dev, buff->paddr, ring->buf_sz, 3118c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (ring->handler) { 3148c2ecf20Sopenharmony_ci vaddr_unalign = buff->payload; 3158c2ecf20Sopenharmony_ci handler_data.data = PTR_ALIGN(vaddr_unalign, 3168c2ecf20Sopenharmony_ci ring->buf_align); 3178c2ecf20Sopenharmony_ci handler_data.data_sz = ring->buf_sz; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci ring->handler(ar, &handler_data); 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci memset(buff, 0, size); 3238c2ecf20Sopenharmony_ci ath11k_dbring_bufs_replenish(ar, ring, buff); 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci spin_unlock_bh(&srng->lock); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_circu_unlock: 3298c2ecf20Sopenharmony_ci rcu_read_unlock(); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci return ret; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_civoid ath11k_dbring_srng_cleanup(struct ath11k *ar, struct ath11k_dbring *ring) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci ath11k_dp_srng_cleanup(ar->ab, &ring->refill_srng); 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_civoid ath11k_dbring_buf_cleanup(struct ath11k *ar, struct ath11k_dbring *ring) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci struct ath11k_dbring_element *buff; 3428c2ecf20Sopenharmony_ci int buf_id; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci spin_lock_bh(&ring->idr_lock); 3458c2ecf20Sopenharmony_ci idr_for_each_entry(&ring->bufs_idr, buff, buf_id) { 3468c2ecf20Sopenharmony_ci idr_remove(&ring->bufs_idr, buf_id); 3478c2ecf20Sopenharmony_ci dma_unmap_single(ar->ab->dev, buff->paddr, 3488c2ecf20Sopenharmony_ci ring->buf_sz, DMA_FROM_DEVICE); 3498c2ecf20Sopenharmony_ci kfree(buff); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci idr_destroy(&ring->bufs_idr); 3538c2ecf20Sopenharmony_ci spin_unlock_bh(&ring->idr_lock); 3548c2ecf20Sopenharmony_ci} 355