brintos

brintos / linux-shallow public Read only

0
0
Text · 8.5 KiB · 788160c Raw
358 lines · c
1// SPDX-License-Identifier: BSD-3-Clause-Clear2/*3 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.4 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.5 */6 7#include "core.h"8#include "debug.h"9 10static int ath12k_dbring_bufs_replenish(struct ath12k *ar,11					struct ath12k_dbring *ring,12					struct ath12k_dbring_element *buff,13					gfp_t gfp)14{15	struct ath12k_base *ab = ar->ab;16	struct hal_srng *srng;17	dma_addr_t paddr;18	void *ptr_aligned, *ptr_unaligned, *desc;19	int ret;20	int buf_id;21	u32 cookie;22 23	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];24 25	lockdep_assert_held(&srng->lock);26 27	ath12k_hal_srng_access_begin(ab, srng);28 29	ptr_unaligned = buff->payload;30	ptr_aligned = PTR_ALIGN(ptr_unaligned, ring->buf_align);31	paddr = dma_map_single(ab->dev, ptr_aligned, ring->buf_sz,32			       DMA_FROM_DEVICE);33 34	ret = dma_mapping_error(ab->dev, paddr);35	if (ret)36		goto err;37 38	spin_lock_bh(&ring->idr_lock);39	buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, gfp);40	spin_unlock_bh(&ring->idr_lock);41	if (buf_id < 0) {42		ret = -ENOBUFS;43		goto err_dma_unmap;44	}45 46	desc = ath12k_hal_srng_src_get_next_entry(ab, srng);47	if (!desc) {48		ret = -ENOENT;49		goto err_idr_remove;50	}51 52	buff->paddr = paddr;53 54	cookie = u32_encode_bits(ar->pdev_idx, DP_RXDMA_BUF_COOKIE_PDEV_ID) |55		 u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);56 57	ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0);58 59	ath12k_hal_srng_access_end(ab, srng);60 61	return 0;62 63err_idr_remove:64	spin_lock_bh(&ring->idr_lock);65	idr_remove(&ring->bufs_idr, buf_id);66	spin_unlock_bh(&ring->idr_lock);67err_dma_unmap:68	dma_unmap_single(ab->dev, paddr, ring->buf_sz,69			 DMA_FROM_DEVICE);70err:71	ath12k_hal_srng_access_end(ab, srng);72	return ret;73}74 75static int ath12k_dbring_fill_bufs(struct ath12k *ar,76				   struct ath12k_dbring *ring,77				   gfp_t gfp)78{79	struct ath12k_dbring_element *buff;80	struct hal_srng *srng;81	struct ath12k_base *ab = ar->ab;82	int num_remain, req_entries, num_free;83	u32 align;84	int size, ret;85 86	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];87 88	spin_lock_bh(&srng->lock);89 90	num_free = ath12k_hal_srng_src_num_free(ab, srng, true);91	req_entries = min(num_free, ring->bufs_max);92	num_remain = req_entries;93	align = ring->buf_align;94	size = sizeof(*buff) + ring->buf_sz + align - 1;95 96	while (num_remain > 0) {97		buff = kzalloc(size, gfp);98		if (!buff)99			break;100 101		ret = ath12k_dbring_bufs_replenish(ar, ring, buff, gfp);102		if (ret) {103			ath12k_warn(ab, "failed to replenish db ring num_remain %d req_ent %d\n",104				    num_remain, req_entries);105			kfree(buff);106			break;107		}108		num_remain--;109	}110 111	spin_unlock_bh(&srng->lock);112 113	return num_remain;114}115 116int ath12k_dbring_wmi_cfg_setup(struct ath12k *ar,117				struct ath12k_dbring *ring,118				enum wmi_direct_buffer_module id)119{120	struct ath12k_wmi_pdev_dma_ring_cfg_arg arg = {0};121	int ret;122 123	if (id >= WMI_DIRECT_BUF_MAX)124		return -EINVAL;125 126	arg.pdev_id = DP_SW2HW_MACID(ring->pdev_id);127	arg.module_id = id;128	arg.base_paddr_lo = lower_32_bits(ring->refill_srng.paddr);129	arg.base_paddr_hi = upper_32_bits(ring->refill_srng.paddr);130	arg.head_idx_paddr_lo = lower_32_bits(ring->hp_addr);131	arg.head_idx_paddr_hi = upper_32_bits(ring->hp_addr);132	arg.tail_idx_paddr_lo = lower_32_bits(ring->tp_addr);133	arg.tail_idx_paddr_hi = upper_32_bits(ring->tp_addr);134	arg.num_elems = ring->bufs_max;135	arg.buf_size = ring->buf_sz;136	arg.num_resp_per_event = ring->num_resp_per_event;137	arg.event_timeout_ms = ring->event_timeout_ms;138 139	ret = ath12k_wmi_pdev_dma_ring_cfg(ar, &arg);140	if (ret) {141		ath12k_warn(ar->ab, "failed to setup db ring cfg\n");142		return ret;143	}144 145	return 0;146}147 148int ath12k_dbring_set_cfg(struct ath12k *ar, struct ath12k_dbring *ring,149			  u32 num_resp_per_event, u32 event_timeout_ms,150			  int (*handler)(struct ath12k *,151					 struct ath12k_dbring_data *))152{153	if (WARN_ON(!ring))154		return -EINVAL;155 156	ring->num_resp_per_event = num_resp_per_event;157	ring->event_timeout_ms = event_timeout_ms;158	ring->handler = handler;159 160	return 0;161}162 163int ath12k_dbring_buf_setup(struct ath12k *ar,164			    struct ath12k_dbring *ring,165			    struct ath12k_dbring_cap *db_cap)166{167	struct ath12k_base *ab = ar->ab;168	struct hal_srng *srng;169	int ret;170 171	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];172	ring->bufs_max = ring->refill_srng.size /173		ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_DIR_BUF);174 175	ring->buf_sz = db_cap->min_buf_sz;176	ring->buf_align = db_cap->min_buf_align;177	ring->pdev_id = db_cap->pdev_id;178	ring->hp_addr = ath12k_hal_srng_get_hp_addr(ab, srng);179	ring->tp_addr = ath12k_hal_srng_get_tp_addr(ab, srng);180 181	ret = ath12k_dbring_fill_bufs(ar, ring, GFP_KERNEL);182 183	return ret;184}185 186int ath12k_dbring_srng_setup(struct ath12k *ar, struct ath12k_dbring *ring,187			     int ring_num, int num_entries)188{189	int ret;190 191	ret = ath12k_dp_srng_setup(ar->ab, &ring->refill_srng, HAL_RXDMA_DIR_BUF,192				   ring_num, ar->pdev_idx, num_entries);193	if (ret < 0) {194		ath12k_warn(ar->ab, "failed to setup srng: %d ring_id %d\n",195			    ret, ring_num);196		goto err;197	}198 199	return 0;200err:201	ath12k_dp_srng_cleanup(ar->ab, &ring->refill_srng);202	return ret;203}204 205int ath12k_dbring_get_cap(struct ath12k_base *ab,206			  u8 pdev_idx,207			  enum wmi_direct_buffer_module id,208			  struct ath12k_dbring_cap *db_cap)209{210	int i;211 212	if (!ab->num_db_cap || !ab->db_caps)213		return -ENOENT;214 215	if (id >= WMI_DIRECT_BUF_MAX)216		return -EINVAL;217 218	for (i = 0; i < ab->num_db_cap; i++) {219		if (pdev_idx == ab->db_caps[i].pdev_id &&220		    id == ab->db_caps[i].id) {221			*db_cap = ab->db_caps[i];222 223			return 0;224		}225	}226 227	return -ENOENT;228}229 230int ath12k_dbring_buffer_release_event(struct ath12k_base *ab,231				       struct ath12k_dbring_buf_release_event *ev)232{233	struct ath12k_dbring *ring = NULL;234	struct hal_srng *srng;235	struct ath12k *ar;236	struct ath12k_dbring_element *buff;237	struct ath12k_dbring_data handler_data;238	struct ath12k_buffer_addr desc;239	u8 *vaddr_unalign;240	u32 num_entry, num_buff_reaped;241	u8 pdev_idx, rbm;242	u32 cookie;243	int buf_id;244	int size;245	dma_addr_t paddr;246	int ret = 0;247 248	pdev_idx = le32_to_cpu(ev->fixed.pdev_id);249 250	if (pdev_idx >= ab->num_radios) {251		ath12k_warn(ab, "Invalid pdev id %d\n", pdev_idx);252		return -EINVAL;253	}254 255	if (ev->fixed.num_buf_release_entry !=256	    ev->fixed.num_meta_data_entry) {257		ath12k_warn(ab, "Buffer entry %d mismatch meta entry %d\n",258			    ev->fixed.num_buf_release_entry,259			    ev->fixed.num_meta_data_entry);260		return -EINVAL;261	}262 263	ar = ab->pdevs[pdev_idx].ar;264 265	rcu_read_lock();266	if (!rcu_dereference(ab->pdevs_active[pdev_idx])) {267		ret = -EINVAL;268		goto rcu_unlock;269	}270 271	switch (ev->fixed.module_id) {272	case WMI_DIRECT_BUF_SPECTRAL:273		break;274	default:275		ring = NULL;276		ath12k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n",277			    ev->fixed.module_id);278		break;279	}280 281	if (!ring) {282		ret = -EINVAL;283		goto rcu_unlock;284	}285 286	srng = &ab->hal.srng_list[ring->refill_srng.ring_id];287	num_entry = le32_to_cpu(ev->fixed.num_buf_release_entry);288	size = sizeof(*buff) + ring->buf_sz + ring->buf_align - 1;289	num_buff_reaped = 0;290 291	spin_lock_bh(&srng->lock);292 293	while (num_buff_reaped < num_entry) {294		desc.info0 = ev->buf_entry[num_buff_reaped].paddr_lo;295		desc.info1 = ev->buf_entry[num_buff_reaped].paddr_hi;296		handler_data.meta = ev->meta_data[num_buff_reaped];297 298		num_buff_reaped++;299 300		ath12k_hal_rx_buf_addr_info_get(&desc, &paddr, &cookie, &rbm);301 302		buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);303 304		spin_lock_bh(&ring->idr_lock);305		buff = idr_find(&ring->bufs_idr, buf_id);306		if (!buff) {307			spin_unlock_bh(&ring->idr_lock);308			continue;309		}310		idr_remove(&ring->bufs_idr, buf_id);311		spin_unlock_bh(&ring->idr_lock);312 313		dma_unmap_single(ab->dev, buff->paddr, ring->buf_sz,314				 DMA_FROM_DEVICE);315 316		if (ring->handler) {317			vaddr_unalign = buff->payload;318			handler_data.data = PTR_ALIGN(vaddr_unalign,319						      ring->buf_align);320			handler_data.data_sz = ring->buf_sz;321 322			ring->handler(ar, &handler_data);323		}324 325		memset(buff, 0, size);326		ath12k_dbring_bufs_replenish(ar, ring, buff, GFP_ATOMIC);327	}328 329	spin_unlock_bh(&srng->lock);330 331rcu_unlock:332	rcu_read_unlock();333 334	return ret;335}336 337void ath12k_dbring_srng_cleanup(struct ath12k *ar, struct ath12k_dbring *ring)338{339	ath12k_dp_srng_cleanup(ar->ab, &ring->refill_srng);340}341 342void ath12k_dbring_buf_cleanup(struct ath12k *ar, struct ath12k_dbring *ring)343{344	struct ath12k_dbring_element *buff;345	int buf_id;346 347	spin_lock_bh(&ring->idr_lock);348	idr_for_each_entry(&ring->bufs_idr, buff, buf_id) {349		idr_remove(&ring->bufs_idr, buf_id);350		dma_unmap_single(ar->ab->dev, buff->paddr,351				 ring->buf_sz, DMA_FROM_DEVICE);352		kfree(buff);353	}354 355	idr_destroy(&ring->bufs_idr);356	spin_unlock_bh(&ring->idr_lock);357}358