1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #include <linux/device.h>
- #include <linux/dma-mapping.h>
- #include <linux/list.h>
- #include <linux/types.h>
- #include <linux/slab.h>
- struct qcom_glink_mem_entry {
- struct device *dev;
- void *va;
- dma_addr_t dma;
- size_t len;
- u32 da;
- struct list_head node;
- };
- static DEFINE_SPINLOCK(qcom_glink_mem_entry_lock);
- static LIST_HEAD(qcom_glink_mem_entries);
- struct qcom_glink_mem_entry *
- qcom_glink_mem_entry_init(struct device *dev, void *va, dma_addr_t dma, size_t len, u32 da)
- {
- struct qcom_glink_mem_entry *mem = NULL;
- unsigned long flags;
- mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- if (!mem)
- return mem;
- mem->dev = dev;
- mem->va = va;
- mem->dma = dma;
- mem->da = da;
- mem->len = len;
- INIT_LIST_HEAD(&mem->node);
- spin_lock_irqsave(&qcom_glink_mem_entry_lock, flags);
- list_add_tail(&mem->node, &qcom_glink_mem_entries);
- spin_unlock_irqrestore(&qcom_glink_mem_entry_lock, flags);
- return mem;
- }
- EXPORT_SYMBOL(qcom_glink_mem_entry_init);
- void qcom_glink_mem_entry_free(struct qcom_glink_mem_entry *mem)
- {
- struct qcom_glink_mem_entry *entry, *tmp;
- unsigned long flags;
- spin_lock_irqsave(&qcom_glink_mem_entry_lock, flags);
- list_for_each_entry_safe(entry, tmp, &qcom_glink_mem_entries, node) {
- if (entry == mem) {
- list_del(&mem->node);
- break;
- }
- }
- spin_unlock_irqrestore(&qcom_glink_mem_entry_lock, flags);
- kfree(mem);
- }
- EXPORT_SYMBOL(qcom_glink_mem_entry_free);
- void *qcom_glink_prepare_da_for_cpu(u64 da, size_t len)
- {
- struct qcom_glink_mem_entry *mem;
- unsigned long flags;
- void *ptr = NULL;
- spin_lock_irqsave(&qcom_glink_mem_entry_lock, flags);
- list_for_each_entry(mem, &qcom_glink_mem_entries, node) {
- int offset = da - mem->da;
- if (!mem->va)
- continue;
- if (offset < 0)
- continue;
- if (offset + len > mem->len)
- continue;
- ptr = mem->va + offset;
- dma_sync_single_for_cpu(mem->dev, da, len, DMA_FROM_DEVICE);
- break;
- }
- spin_unlock_irqrestore(&qcom_glink_mem_entry_lock, flags);
- return ptr;
- }
- EXPORT_SYMBOL(qcom_glink_prepare_da_for_cpu);
|