1bd647855SKarthikeyan Periyasamy // SPDX-License-Identifier: BSD-3-Clause-Clear
2bd647855SKarthikeyan Periyasamy /*
3bd647855SKarthikeyan Periyasamy  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4bd647855SKarthikeyan Periyasamy  */
5bd647855SKarthikeyan Periyasamy 
6bd647855SKarthikeyan Periyasamy #include "core.h"
7bd647855SKarthikeyan Periyasamy #include "debug.h"
8bd647855SKarthikeyan Periyasamy 
9d3d358efSVenkateswara Naralasetty #define ATH11K_DB_MAGIC_VALUE 0xdeadbeaf
10d3d358efSVenkateswara Naralasetty 
ath11k_dbring_validate_buffer(struct ath11k * ar,void * buffer,u32 size)11d3d358efSVenkateswara Naralasetty int ath11k_dbring_validate_buffer(struct ath11k *ar, void *buffer, u32 size)
12d3d358efSVenkateswara Naralasetty {
13d3d358efSVenkateswara Naralasetty 	u32 *temp;
14d3d358efSVenkateswara Naralasetty 	int idx;
15d3d358efSVenkateswara Naralasetty 
16d3d358efSVenkateswara Naralasetty 	size = size >> 2;
17d3d358efSVenkateswara Naralasetty 
18d3d358efSVenkateswara Naralasetty 	for (idx = 0, temp = buffer; idx < size; idx++, temp++) {
19d3d358efSVenkateswara Naralasetty 		if (*temp == ATH11K_DB_MAGIC_VALUE)
20d3d358efSVenkateswara Naralasetty 			return -EINVAL;
21d3d358efSVenkateswara Naralasetty 	}
22d3d358efSVenkateswara Naralasetty 
23d3d358efSVenkateswara Naralasetty 	return 0;
24d3d358efSVenkateswara Naralasetty }
25d3d358efSVenkateswara Naralasetty 
ath11k_dbring_fill_magic_value(struct ath11k * ar,void * buffer,u32 size)26d3d358efSVenkateswara Naralasetty static void ath11k_dbring_fill_magic_value(struct ath11k *ar,
27d3d358efSVenkateswara Naralasetty 					   void *buffer, u32 size)
28d3d358efSVenkateswara Naralasetty {
29*756a7f90SP Praneesh 	/* memset32 function fills buffer payload with the ATH11K_DB_MAGIC_VALUE
30*756a7f90SP Praneesh 	 * and the variable size is expected to be the number of u32 values
31*756a7f90SP Praneesh 	 * to be stored, not the number of bytes.
32*756a7f90SP Praneesh 	 */
33*756a7f90SP Praneesh 	size = size / sizeof(u32);
34d3d358efSVenkateswara Naralasetty 
35*756a7f90SP Praneesh 	memset32(buffer, ATH11K_DB_MAGIC_VALUE, size);
36d3d358efSVenkateswara Naralasetty }
37d3d358efSVenkateswara Naralasetty 
ath11k_dbring_bufs_replenish(struct ath11k * ar,struct ath11k_dbring * ring,struct ath11k_dbring_element * buff,enum wmi_direct_buffer_module id)38bd647855SKarthikeyan Periyasamy static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
39bd647855SKarthikeyan Periyasamy 					struct ath11k_dbring *ring,
40691425b4SVenkateswara Naralasetty 					struct ath11k_dbring_element *buff,
41691425b4SVenkateswara Naralasetty 					enum wmi_direct_buffer_module id)
42bd647855SKarthikeyan Periyasamy {
43bd647855SKarthikeyan Periyasamy 	struct ath11k_base *ab = ar->ab;
44bd647855SKarthikeyan Periyasamy 	struct hal_srng *srng;
45bd647855SKarthikeyan Periyasamy 	dma_addr_t paddr;
46bd647855SKarthikeyan Periyasamy 	void *ptr_aligned, *ptr_unaligned, *desc;
47bd647855SKarthikeyan Periyasamy 	int ret;
48bd647855SKarthikeyan Periyasamy 	int buf_id;
49bd647855SKarthikeyan Periyasamy 	u32 cookie;
50bd647855SKarthikeyan Periyasamy 
51bd647855SKarthikeyan Periyasamy 	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];
52bd647855SKarthikeyan Periyasamy 
53bd647855SKarthikeyan Periyasamy 	lockdep_assert_held(&srng->lock);
54bd647855SKarthikeyan Periyasamy 
55bd647855SKarthikeyan Periyasamy 	ath11k_hal_srng_access_begin(ab, srng);
56bd647855SKarthikeyan Periyasamy 
57bd647855SKarthikeyan Periyasamy 	ptr_unaligned = buff->payload;
58bd647855SKarthikeyan Periyasamy 	ptr_aligned = PTR_ALIGN(ptr_unaligned, ring->buf_align);
59d3d358efSVenkateswara Naralasetty 	ath11k_dbring_fill_magic_value(ar, ptr_aligned, ring->buf_sz);
60bd647855SKarthikeyan Periyasamy 	paddr = dma_map_single(ab->dev, ptr_aligned, ring->buf_sz,
61bd647855SKarthikeyan Periyasamy 			       DMA_FROM_DEVICE);
62bd647855SKarthikeyan Periyasamy 
63bd647855SKarthikeyan Periyasamy 	ret = dma_mapping_error(ab->dev, paddr);
64bd647855SKarthikeyan Periyasamy 	if (ret)
65bd647855SKarthikeyan Periyasamy 		goto err;
66bd647855SKarthikeyan Periyasamy 
67bd647855SKarthikeyan Periyasamy 	spin_lock_bh(&ring->idr_lock);
68aadf7c81SDan Carpenter 	buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, GFP_ATOMIC);
69bd647855SKarthikeyan Periyasamy 	spin_unlock_bh(&ring->idr_lock);
70bd647855SKarthikeyan Periyasamy 	if (buf_id < 0) {
71bd647855SKarthikeyan Periyasamy 		ret = -ENOBUFS;
72bd647855SKarthikeyan Periyasamy 		goto err_dma_unmap;
73bd647855SKarthikeyan Periyasamy 	}
74bd647855SKarthikeyan Periyasamy 
75bd647855SKarthikeyan Periyasamy 	desc = ath11k_hal_srng_src_get_next_entry(ab, srng);
76bd647855SKarthikeyan Periyasamy 	if (!desc) {
77bd647855SKarthikeyan Periyasamy 		ret = -ENOENT;
78bd647855SKarthikeyan Periyasamy 		goto err_idr_remove;
79bd647855SKarthikeyan Periyasamy 	}
80bd647855SKarthikeyan Periyasamy 
81bd647855SKarthikeyan Periyasamy 	buff->paddr = paddr;
82bd647855SKarthikeyan Periyasamy 
83bd647855SKarthikeyan Periyasamy 	cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, ar->pdev_idx) |
84bd647855SKarthikeyan Periyasamy 		 FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id);
85bd647855SKarthikeyan Periyasamy 
86bd647855SKarthikeyan Periyasamy 	ath11k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0);
87bd647855SKarthikeyan Periyasamy 
88691425b4SVenkateswara Naralasetty 	ath11k_debugfs_add_dbring_entry(ar, id, ATH11K_DBG_DBR_EVENT_REPLENISH, srng);
89bd647855SKarthikeyan Periyasamy 	ath11k_hal_srng_access_end(ab, srng);
90bd647855SKarthikeyan Periyasamy 
91bd647855SKarthikeyan Periyasamy 	return 0;
92bd647855SKarthikeyan Periyasamy 
93bd647855SKarthikeyan Periyasamy err_idr_remove:
94bd647855SKarthikeyan Periyasamy 	spin_lock_bh(&ring->idr_lock);
95bd647855SKarthikeyan Periyasamy 	idr_remove(&ring->bufs_idr, buf_id);
96bd647855SKarthikeyan Periyasamy 	spin_unlock_bh(&ring->idr_lock);
97bd647855SKarthikeyan Periyasamy err_dma_unmap:
98bd647855SKarthikeyan Periyasamy 	dma_unmap_single(ab->dev, paddr, ring->buf_sz,
99bd647855SKarthikeyan Periyasamy 			 DMA_FROM_DEVICE);
100bd647855SKarthikeyan Periyasamy err:
101bd647855SKarthikeyan Periyasamy 	ath11k_hal_srng_access_end(ab, srng);
102bd647855SKarthikeyan Periyasamy 	return ret;
103bd647855SKarthikeyan Periyasamy }
104bd647855SKarthikeyan Periyasamy 
ath11k_dbring_fill_bufs(struct ath11k * ar,struct ath11k_dbring * ring,enum wmi_direct_buffer_module id)105bd647855SKarthikeyan Periyasamy static int ath11k_dbring_fill_bufs(struct ath11k *ar,
106691425b4SVenkateswara Naralasetty 				   struct ath11k_dbring *ring,
107691425b4SVenkateswara Naralasetty 				   enum wmi_direct_buffer_module id)
108bd647855SKarthikeyan Periyasamy {
109bd647855SKarthikeyan Periyasamy 	struct ath11k_dbring_element *buff;
110bd647855SKarthikeyan Periyasamy 	struct hal_srng *srng;
111bd647855SKarthikeyan Periyasamy 	int num_remain, req_entries, num_free;
112bd647855SKarthikeyan Periyasamy 	u32 align;
113bd647855SKarthikeyan Periyasamy 	int size, ret;
114bd647855SKarthikeyan Periyasamy 
115bd647855SKarthikeyan Periyasamy 	srng = &ar->ab->hal.srng_list[ring->refill_srng.ring_id];
116bd647855SKarthikeyan Periyasamy 
117bd647855SKarthikeyan Periyasamy 	spin_lock_bh(&srng->lock);
118bd647855SKarthikeyan Periyasamy 
119bd647855SKarthikeyan Periyasamy 	num_free = ath11k_hal_srng_src_num_free(ar->ab, srng, true);
120bd647855SKarthikeyan Periyasamy 	req_entries = min(num_free, ring->bufs_max);
121bd647855SKarthikeyan Periyasamy 	num_remain = req_entries;
122bd647855SKarthikeyan Periyasamy 	align = ring->buf_align;
123bd77f6b1SRameshkumar Sundaram 	size = ring->buf_sz + align - 1;
124bd647855SKarthikeyan Periyasamy 
125bd647855SKarthikeyan Periyasamy 	while (num_remain > 0) {
126bd77f6b1SRameshkumar Sundaram 		buff = kzalloc(sizeof(*buff), GFP_ATOMIC);
127bd647855SKarthikeyan Periyasamy 		if (!buff)
128bd647855SKarthikeyan Periyasamy 			break;
129bd647855SKarthikeyan Periyasamy 
130bd77f6b1SRameshkumar Sundaram 		buff->payload = kzalloc(size, GFP_ATOMIC);
131bd77f6b1SRameshkumar Sundaram 		if (!buff->payload) {
132bd77f6b1SRameshkumar Sundaram 			kfree(buff);
133bd77f6b1SRameshkumar Sundaram 			break;
134bd77f6b1SRameshkumar Sundaram 		}
135691425b4SVenkateswara Naralasetty 		ret = ath11k_dbring_bufs_replenish(ar, ring, buff, id);
136bd647855SKarthikeyan Periyasamy 		if (ret) {
137bd647855SKarthikeyan Periyasamy 			ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n",
138bd647855SKarthikeyan Periyasamy 				    num_remain, req_entries);
139bd77f6b1SRameshkumar Sundaram 			kfree(buff->payload);
140bd647855SKarthikeyan Periyasamy 			kfree(buff);
141bd647855SKarthikeyan Periyasamy 			break;
142bd647855SKarthikeyan Periyasamy 		}
143bd647855SKarthikeyan Periyasamy 		num_remain--;
144bd647855SKarthikeyan Periyasamy 	}
145bd647855SKarthikeyan Periyasamy 
146bd647855SKarthikeyan Periyasamy 	spin_unlock_bh(&srng->lock);
147bd647855SKarthikeyan Periyasamy 
148bd647855SKarthikeyan Periyasamy 	return num_remain;
149bd647855SKarthikeyan Periyasamy }
150bd647855SKarthikeyan Periyasamy 
ath11k_dbring_wmi_cfg_setup(struct ath11k * ar,struct ath11k_dbring * ring,enum wmi_direct_buffer_module id)151bd647855SKarthikeyan Periyasamy int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
152bd647855SKarthikeyan Periyasamy 				struct ath11k_dbring *ring,
153bd647855SKarthikeyan Periyasamy 				enum wmi_direct_buffer_module id)
154bd647855SKarthikeyan Periyasamy {
155bd647855SKarthikeyan Periyasamy 	struct ath11k_wmi_pdev_dma_ring_cfg_req_cmd param = {0};
156bd647855SKarthikeyan Periyasamy 	int ret;
157bd647855SKarthikeyan Periyasamy 
158bd647855SKarthikeyan Periyasamy 	if (id >= WMI_DIRECT_BUF_MAX)
159bd647855SKarthikeyan Periyasamy 		return -EINVAL;
160bd647855SKarthikeyan Periyasamy 
161bd647855SKarthikeyan Periyasamy 	param.pdev_id		= DP_SW2HW_MACID(ring->pdev_id);
162bd647855SKarthikeyan Periyasamy 	param.module_id		= id;
163bd647855SKarthikeyan Periyasamy 	param.base_paddr_lo	= lower_32_bits(ring->refill_srng.paddr);
164bd647855SKarthikeyan Periyasamy 	param.base_paddr_hi	= upper_32_bits(ring->refill_srng.paddr);
165bd647855SKarthikeyan Periyasamy 	param.head_idx_paddr_lo	= lower_32_bits(ring->hp_addr);
166bd647855SKarthikeyan Periyasamy 	param.head_idx_paddr_hi = upper_32_bits(ring->hp_addr);
167bd647855SKarthikeyan Periyasamy 	param.tail_idx_paddr_lo = lower_32_bits(ring->tp_addr);
168bd647855SKarthikeyan Periyasamy 	param.tail_idx_paddr_hi = upper_32_bits(ring->tp_addr);
169bd647855SKarthikeyan Periyasamy 	param.num_elems		= ring->bufs_max;
170bd647855SKarthikeyan Periyasamy 	param.buf_size		= ring->buf_sz;
171bd647855SKarthikeyan Periyasamy 	param.num_resp_per_event = ring->num_resp_per_event;
172bd647855SKarthikeyan Periyasamy 	param.event_timeout_ms	= ring->event_timeout_ms;
173bd647855SKarthikeyan Periyasamy 
174bd647855SKarthikeyan Periyasamy 	ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
175bd647855SKarthikeyan Periyasamy 	if (ret) {
176bd647855SKarthikeyan Periyasamy 		ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
177bd647855SKarthikeyan Periyasamy 		return ret;
178bd647855SKarthikeyan Periyasamy 	}
179bd647855SKarthikeyan Periyasamy 
180bd647855SKarthikeyan Periyasamy 	return 0;
181bd647855SKarthikeyan Periyasamy }
182bd647855SKarthikeyan Periyasamy 
ath11k_dbring_set_cfg(struct ath11k * ar,struct ath11k_dbring * ring,u32 num_resp_per_event,u32 event_timeout_ms,int (* handler)(struct ath11k *,struct ath11k_dbring_data *))183bd647855SKarthikeyan Periyasamy int ath11k_dbring_set_cfg(struct ath11k *ar, struct ath11k_dbring *ring,
184bd647855SKarthikeyan Periyasamy 			  u32 num_resp_per_event, u32 event_timeout_ms,
185bd647855SKarthikeyan Periyasamy 			  int (*handler)(struct ath11k *,
186bd647855SKarthikeyan Periyasamy 					 struct ath11k_dbring_data *))
187bd647855SKarthikeyan Periyasamy {
188bd647855SKarthikeyan Periyasamy 	if (WARN_ON(!ring))
189bd647855SKarthikeyan Periyasamy 		return -EINVAL;
190bd647855SKarthikeyan Periyasamy 
191bd647855SKarthikeyan Periyasamy 	ring->num_resp_per_event = num_resp_per_event;
192bd647855SKarthikeyan Periyasamy 	ring->event_timeout_ms = event_timeout_ms;
193bd647855SKarthikeyan Periyasamy 	ring->handler = handler;
194bd647855SKarthikeyan Periyasamy 
195bd647855SKarthikeyan Periyasamy 	return 0;
196bd647855SKarthikeyan Periyasamy }
197bd647855SKarthikeyan Periyasamy 
ath11k_dbring_buf_setup(struct ath11k * ar,struct ath11k_dbring * ring,struct ath11k_dbring_cap * db_cap)198bd647855SKarthikeyan Periyasamy int ath11k_dbring_buf_setup(struct ath11k *ar,
199bd647855SKarthikeyan Periyasamy 			    struct ath11k_dbring *ring,
200bd647855SKarthikeyan Periyasamy 			    struct ath11k_dbring_cap *db_cap)
201bd647855SKarthikeyan Periyasamy {
202bd647855SKarthikeyan Periyasamy 	struct ath11k_base *ab = ar->ab;
203bd647855SKarthikeyan Periyasamy 	struct hal_srng *srng;
204bd647855SKarthikeyan Periyasamy 	int ret;
205bd647855SKarthikeyan Periyasamy 
206bd647855SKarthikeyan Periyasamy 	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];
207bd647855SKarthikeyan Periyasamy 	ring->bufs_max = ring->refill_srng.size /
208f7eb4b04SKalle Valo 		ath11k_hal_srng_get_entrysize(ab, HAL_RXDMA_DIR_BUF);
209bd647855SKarthikeyan Periyasamy 
210bd647855SKarthikeyan Periyasamy 	ring->buf_sz = db_cap->min_buf_sz;
211bd647855SKarthikeyan Periyasamy 	ring->buf_align = db_cap->min_buf_align;
212bd647855SKarthikeyan Periyasamy 	ring->pdev_id = db_cap->pdev_id;
213bd647855SKarthikeyan Periyasamy 	ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng);
214bd647855SKarthikeyan Periyasamy 	ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng);
215bd647855SKarthikeyan Periyasamy 
216691425b4SVenkateswara Naralasetty 	ret = ath11k_dbring_fill_bufs(ar, ring, db_cap->id);
217bd647855SKarthikeyan Periyasamy 
218bd647855SKarthikeyan Periyasamy 	return ret;
219bd647855SKarthikeyan Periyasamy }
220bd647855SKarthikeyan Periyasamy 
ath11k_dbring_srng_setup(struct ath11k * ar,struct ath11k_dbring * ring,int ring_num,int num_entries)221bd647855SKarthikeyan Periyasamy int ath11k_dbring_srng_setup(struct ath11k *ar, struct ath11k_dbring *ring,
222bd647855SKarthikeyan Periyasamy 			     int ring_num, int num_entries)
223bd647855SKarthikeyan Periyasamy {
224bd647855SKarthikeyan Periyasamy 	int ret;
225bd647855SKarthikeyan Periyasamy 
226bd647855SKarthikeyan Periyasamy 	ret = ath11k_dp_srng_setup(ar->ab, &ring->refill_srng, HAL_RXDMA_DIR_BUF,
227bd647855SKarthikeyan Periyasamy 				   ring_num, ar->pdev_idx, num_entries);
228bd647855SKarthikeyan Periyasamy 	if (ret < 0) {
229bd647855SKarthikeyan Periyasamy 		ath11k_warn(ar->ab, "failed to setup srng: %d ring_id %d\n",
230bd647855SKarthikeyan Periyasamy 			    ret, ring_num);
231bd647855SKarthikeyan Periyasamy 		goto err;
232bd647855SKarthikeyan Periyasamy 	}
233bd647855SKarthikeyan Periyasamy 
234bd647855SKarthikeyan Periyasamy 	return 0;
235bd647855SKarthikeyan Periyasamy err:
236bd647855SKarthikeyan Periyasamy 	ath11k_dp_srng_cleanup(ar->ab, &ring->refill_srng);
237bd647855SKarthikeyan Periyasamy 	return ret;
238bd647855SKarthikeyan Periyasamy }
239bd647855SKarthikeyan Periyasamy 
ath11k_dbring_get_cap(struct ath11k_base * ab,u8 pdev_idx,enum wmi_direct_buffer_module id,struct ath11k_dbring_cap * db_cap)240bd647855SKarthikeyan Periyasamy int ath11k_dbring_get_cap(struct ath11k_base *ab,
241bd647855SKarthikeyan Periyasamy 			  u8 pdev_idx,
242bd647855SKarthikeyan Periyasamy 			  enum wmi_direct_buffer_module id,
243bd647855SKarthikeyan Periyasamy 			  struct ath11k_dbring_cap *db_cap)
244bd647855SKarthikeyan Periyasamy {
245bd647855SKarthikeyan Periyasamy 	int i;
246bd647855SKarthikeyan Periyasamy 
247bd647855SKarthikeyan Periyasamy 	if (!ab->num_db_cap || !ab->db_caps)
248bd647855SKarthikeyan Periyasamy 		return -ENOENT;
249bd647855SKarthikeyan Periyasamy 
250bd647855SKarthikeyan Periyasamy 	if (id >= WMI_DIRECT_BUF_MAX)
251bd647855SKarthikeyan Periyasamy 		return -EINVAL;
252bd647855SKarthikeyan Periyasamy 
253bd647855SKarthikeyan Periyasamy 	for (i = 0; i < ab->num_db_cap; i++) {
254bd647855SKarthikeyan Periyasamy 		if (pdev_idx == ab->db_caps[i].pdev_id &&
255bd647855SKarthikeyan Periyasamy 		    id == ab->db_caps[i].id) {
256bd647855SKarthikeyan Periyasamy 			*db_cap = ab->db_caps[i];
257bd647855SKarthikeyan Periyasamy 
258bd647855SKarthikeyan Periyasamy 			return 0;
259bd647855SKarthikeyan Periyasamy 		}
260bd647855SKarthikeyan Periyasamy 	}
261bd647855SKarthikeyan Periyasamy 
262bd647855SKarthikeyan Periyasamy 	return -ENOENT;
263bd647855SKarthikeyan Periyasamy }
264bd647855SKarthikeyan Periyasamy 
ath11k_dbring_buffer_release_event(struct ath11k_base * ab,struct ath11k_dbring_buf_release_event * ev)265bd647855SKarthikeyan Periyasamy int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
266bd647855SKarthikeyan Periyasamy 				       struct ath11k_dbring_buf_release_event *ev)
267bd647855SKarthikeyan Periyasamy {
268bd647855SKarthikeyan Periyasamy 	struct ath11k_dbring *ring;
269bd647855SKarthikeyan Periyasamy 	struct hal_srng *srng;
270bd647855SKarthikeyan Periyasamy 	struct ath11k *ar;
271bd647855SKarthikeyan Periyasamy 	struct ath11k_dbring_element *buff;
272bd647855SKarthikeyan Periyasamy 	struct ath11k_dbring_data handler_data;
273bd647855SKarthikeyan Periyasamy 	struct ath11k_buffer_addr desc;
274bd647855SKarthikeyan Periyasamy 	u8 *vaddr_unalign;
275bd647855SKarthikeyan Periyasamy 	u32 num_entry, num_buff_reaped;
276691425b4SVenkateswara Naralasetty 	u8 pdev_idx, rbm, module_id;
277bd647855SKarthikeyan Periyasamy 	u32 cookie;
278bd647855SKarthikeyan Periyasamy 	int buf_id;
279bd647855SKarthikeyan Periyasamy 	int size;
280bd647855SKarthikeyan Periyasamy 	dma_addr_t paddr;
281bd647855SKarthikeyan Periyasamy 	int ret = 0;
282bd647855SKarthikeyan Periyasamy 
283bd647855SKarthikeyan Periyasamy 	pdev_idx = ev->fixed.pdev_id;
284691425b4SVenkateswara Naralasetty 	module_id = ev->fixed.module_id;
285bd647855SKarthikeyan Periyasamy 
286bd647855SKarthikeyan Periyasamy 	if (pdev_idx >= ab->num_radios) {
287bd647855SKarthikeyan Periyasamy 		ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx);
288bd647855SKarthikeyan Periyasamy 		return -EINVAL;
289bd647855SKarthikeyan Periyasamy 	}
290bd647855SKarthikeyan Periyasamy 
291bd647855SKarthikeyan Periyasamy 	if (ev->fixed.num_buf_release_entry !=
292bd647855SKarthikeyan Periyasamy 	    ev->fixed.num_meta_data_entry) {
293bd647855SKarthikeyan Periyasamy 		ath11k_warn(ab, "Buffer entry %d mismatch meta entry %d\n",
294bd647855SKarthikeyan Periyasamy 			    ev->fixed.num_buf_release_entry,
295bd647855SKarthikeyan Periyasamy 			    ev->fixed.num_meta_data_entry);
296bd647855SKarthikeyan Periyasamy 		return -EINVAL;
297bd647855SKarthikeyan Periyasamy 	}
298bd647855SKarthikeyan Periyasamy 
299bd647855SKarthikeyan Periyasamy 	ar = ab->pdevs[pdev_idx].ar;
300bd647855SKarthikeyan Periyasamy 
301bd647855SKarthikeyan Periyasamy 	rcu_read_lock();
302bd647855SKarthikeyan Periyasamy 	if (!rcu_dereference(ab->pdevs_active[pdev_idx])) {
303bd647855SKarthikeyan Periyasamy 		ret = -EINVAL;
304bd647855SKarthikeyan Periyasamy 		goto rcu_unlock;
305bd647855SKarthikeyan Periyasamy 	}
306bd647855SKarthikeyan Periyasamy 
307bd647855SKarthikeyan Periyasamy 	switch (ev->fixed.module_id) {
3089d11b7bfSKarthikeyan Periyasamy 	case WMI_DIRECT_BUF_SPECTRAL:
3099d11b7bfSKarthikeyan Periyasamy 		ring = ath11k_spectral_get_dbring(ar);
3109d11b7bfSKarthikeyan Periyasamy 		break;
311bd647855SKarthikeyan Periyasamy 	default:
312bd647855SKarthikeyan Periyasamy 		ring = NULL;
313bd647855SKarthikeyan Periyasamy 		ath11k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n",
314bd647855SKarthikeyan Periyasamy 			    ev->fixed.module_id);
315bd647855SKarthikeyan Periyasamy 		break;
316bd647855SKarthikeyan Periyasamy 	}
317bd647855SKarthikeyan Periyasamy 
318bd647855SKarthikeyan Periyasamy 	if (!ring) {
319bd647855SKarthikeyan Periyasamy 		ret = -EINVAL;
320bd647855SKarthikeyan Periyasamy 		goto rcu_unlock;
321bd647855SKarthikeyan Periyasamy 	}
322bd647855SKarthikeyan Periyasamy 
323bd647855SKarthikeyan Periyasamy 	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];
324bd647855SKarthikeyan Periyasamy 	num_entry = ev->fixed.num_buf_release_entry;
325bd77f6b1SRameshkumar Sundaram 	size = ring->buf_sz + ring->buf_align - 1;
326bd647855SKarthikeyan Periyasamy 	num_buff_reaped = 0;
327bd647855SKarthikeyan Periyasamy 
328bd647855SKarthikeyan Periyasamy 	spin_lock_bh(&srng->lock);
329bd647855SKarthikeyan Periyasamy 
330bd647855SKarthikeyan Periyasamy 	while (num_buff_reaped < num_entry) {
331bd647855SKarthikeyan Periyasamy 		desc.info0 = ev->buf_entry[num_buff_reaped].paddr_lo;
332bd647855SKarthikeyan Periyasamy 		desc.info1 = ev->buf_entry[num_buff_reaped].paddr_hi;
333bd647855SKarthikeyan Periyasamy 		handler_data.meta = ev->meta_data[num_buff_reaped];
334bd647855SKarthikeyan Periyasamy 
335bd647855SKarthikeyan Periyasamy 		num_buff_reaped++;
336bd647855SKarthikeyan Periyasamy 
337bd647855SKarthikeyan Periyasamy 		ath11k_hal_rx_buf_addr_info_get(&desc, &paddr, &cookie, &rbm);
338bd647855SKarthikeyan Periyasamy 
339bd647855SKarthikeyan Periyasamy 		buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID, cookie);
340bd647855SKarthikeyan Periyasamy 
341bd647855SKarthikeyan Periyasamy 		spin_lock_bh(&ring->idr_lock);
342bd647855SKarthikeyan Periyasamy 		buff = idr_find(&ring->bufs_idr, buf_id);
343bd647855SKarthikeyan Periyasamy 		if (!buff) {
344bd647855SKarthikeyan Periyasamy 			spin_unlock_bh(&ring->idr_lock);
345bd647855SKarthikeyan Periyasamy 			continue;
346bd647855SKarthikeyan Periyasamy 		}
347bd647855SKarthikeyan Periyasamy 		idr_remove(&ring->bufs_idr, buf_id);
348bd647855SKarthikeyan Periyasamy 		spin_unlock_bh(&ring->idr_lock);
349bd647855SKarthikeyan Periyasamy 
350bd647855SKarthikeyan Periyasamy 		dma_unmap_single(ab->dev, buff->paddr, ring->buf_sz,
351bd647855SKarthikeyan Periyasamy 				 DMA_FROM_DEVICE);
352bd647855SKarthikeyan Periyasamy 
353691425b4SVenkateswara Naralasetty 		ath11k_debugfs_add_dbring_entry(ar, module_id,
354691425b4SVenkateswara Naralasetty 						ATH11K_DBG_DBR_EVENT_RX, srng);
355691425b4SVenkateswara Naralasetty 
356bd647855SKarthikeyan Periyasamy 		if (ring->handler) {
357bd647855SKarthikeyan Periyasamy 			vaddr_unalign = buff->payload;
358bd647855SKarthikeyan Periyasamy 			handler_data.data = PTR_ALIGN(vaddr_unalign,
359bd647855SKarthikeyan Periyasamy 						      ring->buf_align);
360bd647855SKarthikeyan Periyasamy 			handler_data.data_sz = ring->buf_sz;
361bd647855SKarthikeyan Periyasamy 
362bd647855SKarthikeyan Periyasamy 			ring->handler(ar, &handler_data);
363bd647855SKarthikeyan Periyasamy 		}
364bd647855SKarthikeyan Periyasamy 
365bd77f6b1SRameshkumar Sundaram 		buff->paddr = 0;
366bd77f6b1SRameshkumar Sundaram 		memset(buff->payload, 0, size);
367691425b4SVenkateswara Naralasetty 		ath11k_dbring_bufs_replenish(ar, ring, buff, module_id);
368bd647855SKarthikeyan Periyasamy 	}
369bd647855SKarthikeyan Periyasamy 
370bd647855SKarthikeyan Periyasamy 	spin_unlock_bh(&srng->lock);
371bd647855SKarthikeyan Periyasamy 
372bd647855SKarthikeyan Periyasamy rcu_unlock:
373bd647855SKarthikeyan Periyasamy 	rcu_read_unlock();
374bd647855SKarthikeyan Periyasamy 
375bd647855SKarthikeyan Periyasamy 	return ret;
376bd647855SKarthikeyan Periyasamy }
377bd647855SKarthikeyan Periyasamy 
ath11k_dbring_srng_cleanup(struct ath11k * ar,struct ath11k_dbring * ring)378bd647855SKarthikeyan Periyasamy void ath11k_dbring_srng_cleanup(struct ath11k *ar, struct ath11k_dbring *ring)
379bd647855SKarthikeyan Periyasamy {
380bd647855SKarthikeyan Periyasamy 	ath11k_dp_srng_cleanup(ar->ab, &ring->refill_srng);
381bd647855SKarthikeyan Periyasamy }
382bd647855SKarthikeyan Periyasamy 
ath11k_dbring_buf_cleanup(struct ath11k * ar,struct ath11k_dbring * ring)383bd647855SKarthikeyan Periyasamy void ath11k_dbring_buf_cleanup(struct ath11k *ar, struct ath11k_dbring *ring)
384bd647855SKarthikeyan Periyasamy {
385bd647855SKarthikeyan Periyasamy 	struct ath11k_dbring_element *buff;
386bd647855SKarthikeyan Periyasamy 	int buf_id;
387bd647855SKarthikeyan Periyasamy 
388bd647855SKarthikeyan Periyasamy 	spin_lock_bh(&ring->idr_lock);
389bd647855SKarthikeyan Periyasamy 	idr_for_each_entry(&ring->bufs_idr, buff, buf_id) {
390bd647855SKarthikeyan Periyasamy 		idr_remove(&ring->bufs_idr, buf_id);
391bd647855SKarthikeyan Periyasamy 		dma_unmap_single(ar->ab->dev, buff->paddr,
392bd647855SKarthikeyan Periyasamy 				 ring->buf_sz, DMA_FROM_DEVICE);
393bd77f6b1SRameshkumar Sundaram 		kfree(buff->payload);
394bd647855SKarthikeyan Periyasamy 		kfree(buff);
395bd647855SKarthikeyan Periyasamy 	}
396bd647855SKarthikeyan Periyasamy 
397bd647855SKarthikeyan Periyasamy 	idr_destroy(&ring->bufs_idr);
398bd647855SKarthikeyan Periyasamy 	spin_unlock_bh(&ring->idr_lock);
399bd647855SKarthikeyan Periyasamy }
400