Merge "soc: qcom: dmesg_dumper: alloc shared memory from VM_COMMON_MEM"
This commit is contained in:
commit
082db61590
@ -1,11 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.*/
|
||||
|
||||
#include <linux/dma-direct.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kmsg_dump.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/proc_fs.h>
|
||||
@ -83,13 +86,29 @@ static int qcom_ddump_map_memory(struct qcom_dmesg_dumper *qdd)
|
||||
{
|
||||
struct device *dev = qdd->dev;
|
||||
struct device_node *np;
|
||||
u32 size;
|
||||
u32 size = 0;
|
||||
int ret;
|
||||
|
||||
if (qdd->primary_vm) {
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: dma_set_mask_and_coherent failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to initialize CMA mem, ret %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(qdd->dev->of_node, "shared-buffer-size", &size);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to get shared memory size, ret %d\n",
|
||||
__func__, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdd->size = size;
|
||||
} else {
|
||||
np = qcom_ddump_svm_of_parse(qdd);
|
||||
@ -169,7 +188,7 @@ static int qcom_ddump_share_mem(struct qcom_dmesg_dumper *qdd, gh_vmid_t self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qcom_ddump_unshare_mem(struct qcom_dmesg_dumper *qdd, gh_vmid_t self,
|
||||
static int qcom_ddump_unshare_mem(struct qcom_dmesg_dumper *qdd, gh_vmid_t self,
|
||||
gh_vmid_t peer)
|
||||
{
|
||||
struct qcom_scm_vmperm dst_vmlist[] = {{self,
|
||||
@ -183,10 +202,11 @@ static void qcom_ddump_unshare_mem(struct qcom_dmesg_dumper *qdd, gh_vmid_t self
|
||||
|
||||
ret = qcom_scm_assign_mem(qdd->res.start, resource_size(&qdd->res),
|
||||
&src_vmid, dst_vmlist, ARRAY_SIZE(dst_vmlist));
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(qdd->dev, "unshare mem assign call failed with %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_ddump_rm_cb(struct notifier_block *nb, unsigned long cmd,
|
||||
@ -194,6 +214,7 @@ static int qcom_ddump_rm_cb(struct notifier_block *nb, unsigned long cmd,
|
||||
{
|
||||
struct gh_rm_notif_vm_status_payload *vm_status_payload;
|
||||
struct qcom_dmesg_dumper *qdd;
|
||||
dma_addr_t dma_handle;
|
||||
gh_vmid_t peer_vmid;
|
||||
gh_vmid_t self_vmid;
|
||||
int ret;
|
||||
@ -215,13 +236,13 @@ static int qcom_ddump_rm_cb(struct notifier_block *nb, unsigned long cmd,
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (vm_status_payload->vm_status == GH_RM_VM_STATUS_READY) {
|
||||
qdd->base = kzalloc(qdd->size, GFP_KERNEL);
|
||||
qdd->base = dma_alloc_coherent(qdd->dev, qdd->size, &dma_handle, GFP_KERNEL);
|
||||
if (!qdd->base) {
|
||||
dev_err(qdd->dev, "Failed to alloc memory\n");
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
qdd->res.start = virt_to_phys(qdd->base);
|
||||
qdd->res.start = dma_to_phys(qdd->dev, dma_handle);
|
||||
qdd->res.end = qdd->res.start + qdd->size - 1;
|
||||
strscpy(qdd->md_entry.name, "VM_LOG", sizeof(qdd->md_entry.name));
|
||||
qdd->md_entry.virt_addr = (uintptr_t)qdd->base;
|
||||
@ -233,18 +254,25 @@ static int qcom_ddump_rm_cb(struct notifier_block *nb, unsigned long cmd,
|
||||
|
||||
if (qcom_ddump_share_mem(qdd, self_vmid, peer_vmid)) {
|
||||
dev_err(qdd->dev, "Failed to share memory\n");
|
||||
return NOTIFY_DONE;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
vm_status_ready = true;
|
||||
}
|
||||
|
||||
if (vm_status_payload->vm_status == GH_RM_VM_STATUS_RESET) {
|
||||
qcom_ddump_unshare_mem(qdd, self_vmid, peer_vmid);
|
||||
vm_status_ready = false;
|
||||
if (!qcom_ddump_unshare_mem(qdd, self_vmid, peer_vmid))
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
|
||||
free_mem:
|
||||
dma_free_coherent(qdd->dev, qdd->size, qdd->base,
|
||||
phys_to_dma(qdd->dev, qdd->res.start));
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static inline int qcom_ddump_gh_kick(struct qcom_dmesg_dumper *qdd)
|
||||
@ -488,6 +516,8 @@ static int qcom_ddump_probe(struct platform_device *pdev)
|
||||
|
||||
static int qcom_ddump_remove(struct platform_device *pdev)
|
||||
{
|
||||
gh_vmid_t peer_vmid;
|
||||
gh_vmid_t self_vmid;
|
||||
int ret;
|
||||
struct qcom_dmesg_dumper *qdd = platform_get_drvdata(pdev);
|
||||
|
||||
@ -504,8 +534,21 @@ static int qcom_ddump_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (qdd->primary_vm) {
|
||||
kfree(qdd->base);
|
||||
gh_rm_unregister_notifier(&qdd->rm_nb);
|
||||
ret = ghd_rm_get_vmid(qdd->peer_name, &peer_vmid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ghd_rm_get_vmid(GH_PRIMARY_VM, &self_vmid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_ddump_unshare_mem(qdd, self_vmid, peer_vmid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dma_free_coherent(qdd->dev, qdd->size, qdd->base,
|
||||
phys_to_dma(qdd->dev, qdd->res.start));
|
||||
} else {
|
||||
ret = kmsg_dump_unregister(&qdd->dump);
|
||||
if (ret)
|
||||
|
Loading…
Reference in New Issue
Block a user