msm-mmrm: add para virtualization backend
Add para virtualization backend. Change-Id: Ifa25e422c04ef4dafb152130f303d0a217429c32 Signed-off-by: Mark Bao <quic_mbao@quicinc.com>
This commit is contained in:
16
Android.mk
16
Android.mk
@@ -45,3 +45,19 @@ LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
# Include kp_module.ko in the /vendor/lib/modules (vendor.img)
|
||||
# BOARD_VENDOR_KERNEL_MODULES += $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
|
||||
ifeq ($(CONFIG_MSM_MMRM_VM),y)
|
||||
include $(CLEAR_VARS)
|
||||
# For incremental compilation
|
||||
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
|
||||
LOCAL_MODULE := mmrm_vm_be.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := vm/be/mmrm_vm_be.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
LOCAL_INIT_RC := vm/be/src/mmrm_vm_be.rc
|
||||
LOCAL_C_INCLUDES := vm/common/inc/
|
||||
# Include kp_module.ko in the /vendor/lib/modules (vendor.img)
|
||||
# BOARD_VENDOR_KERNEL_MODULES += $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
endif
|
||||
|
10
Kbuild
10
Kbuild
@@ -1,5 +1,15 @@
|
||||
|
||||
include $(MMRM_ROOT)/config/waipiommrm.conf
|
||||
LINUXINCLUDE += -include $(MMRM_ROOT)/config/waipiommrmconf.h
|
||||
|
||||
ifneq ($(CONFIG_ARCH_QTI_VM), y)
|
||||
|
||||
obj-m += driver/
|
||||
obj-m += test/
|
||||
|
||||
ifeq ($(CONFIG_MSM_MMRM_VM),y)
|
||||
LINUXINCLUDE += -I$(MMRM_ROOT)/vm/common/inc/
|
||||
obj-m += vm/be/
|
||||
endif
|
||||
|
||||
endif
|
||||
|
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
export CONFIG_MSM_MMRM=y
|
||||
export CONFIG_MSM_MMRM_VM=n
|
||||
|
@@ -278,6 +278,19 @@ err_exit:
|
||||
}
|
||||
EXPORT_SYMBOL(mmrm_client_get_value);
|
||||
|
||||
int mmrm_client_get_clk_count(void)
|
||||
{
|
||||
struct mmrm_sw_clk_mgr_info *sinfo;
|
||||
|
||||
if (drv_data == (void *) -EPROBE_DEFER)
|
||||
return 0;
|
||||
|
||||
sinfo = &(drv_data->clk_mgr->data.sw_info);
|
||||
|
||||
return sinfo->tot_clk_clients;
|
||||
}
|
||||
EXPORT_SYMBOL(mmrm_client_get_clk_count);
|
||||
|
||||
static int sysfs_get_param(const char *buf, u32 *param)
|
||||
{
|
||||
int base;
|
||||
|
9
vm/be/Kbuild
Normal file
9
vm/be/Kbuild
Normal file
@@ -0,0 +1,9 @@
|
||||
ifeq ($(CONFIG_MSM_MMRM_VM),y)
|
||||
LINUXINCLUDE += -I$(MMRM_ROOT)/vm/be/src -I$(MMRM_ROOT)/driver/src
|
||||
|
||||
obj-m += mmrm_vm_be.o
|
||||
mmrm_vm_be-objs := src/mmrm_vm_be_main.o \
|
||||
src/mmrm_vm_be_dispatch.o \
|
||||
src/mmrm_vm_be_msgq.o \
|
||||
../cmn/src/mmrm_vm_debug.o
|
||||
endif
|
32
vm/be/src/mmrm_vm_be.h
Normal file
32
vm/be/src/mmrm_vm_be.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MMRM_VM_BE_H_
|
||||
#define _MMRM_VM_BE_H_
|
||||
|
||||
#include <linux/soc/qcom/msm_mmrm.h>
|
||||
#include <mmrm_vm_interface.h>
|
||||
|
||||
/*
|
||||
* mmrm_vm_be_recv -- BE message receiving thread call this function
|
||||
* for transfer receiving packet to BE
|
||||
* @mmrm_vm: device driver info
|
||||
* @data: message pointer
|
||||
* @size: message size
|
||||
*/
|
||||
int mmrm_vm_be_recv(struct mmrm_vm_driver_data *mmrm_vm, void *data, size_t size);
|
||||
|
||||
/*
|
||||
* mmrm_vm_be_send_response -- BE message receiving thread call this function
|
||||
* for sending back API calling result to FE
|
||||
* @mmrm_vm: specific device driver info
|
||||
* @size: message size
|
||||
*/
|
||||
int mmrm_vm_be_send_response(struct mmrm_vm_driver_data *mmrm_vm, void *msg);
|
||||
|
||||
|
||||
#endif /* _MMRM_VM_BE_H_ */
|
||||
|
||||
|
9
vm/be/src/mmrm_vm_be.rc
Normal file
9
vm/be/src/mmrm_vm_be.rc
Normal file
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
on boot
|
||||
insmod /vendor/lib/modules/mmrm_vm_be.ko
|
||||
|
||||
|
244
vm/be/src/mmrm_vm_be_dispatch.c
Normal file
244
vm/be/src/mmrm_vm_be_dispatch.c
Normal file
@@ -0,0 +1,244 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "mmrm_vm_debug.h"
|
||||
#include "mmrm_vm_interface.h"
|
||||
#include "mmrm_vm_msgq.h"
|
||||
#include "mmrm_vm_be.h"
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_send_response - send response to FE
|
||||
* mmrm_vm: driver private data
|
||||
* msg: response message
|
||||
*/
|
||||
|
||||
int mmrm_vm_be_send_response(struct mmrm_vm_driver_data *mmrm_vm, void *msg)
|
||||
{
|
||||
struct mmrm_vm_response_msg_pkt *ppkt = (struct mmrm_vm_response_msg_pkt *)msg;
|
||||
struct mmrm_vm_msg_hdr *hdr = &ppkt->hdr;
|
||||
size_t msg_size = sizeof(*hdr) + hdr->size;
|
||||
int rc;
|
||||
|
||||
hdr->version = MMRM_VM_VER_1;
|
||||
hdr->type = MMRM_VM_TYPE_DATA;
|
||||
hdr->flags = 0;
|
||||
|
||||
rc = mmrm_vm_msgq_send(mmrm_vm, msg, msg_size);
|
||||
d_mpr_l("%s: size:%d rc=%d\n", __func__, msg_size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_client_register - call mmrm API to register client
|
||||
* mmrm_vm: driver private data
|
||||
* req: request parameters
|
||||
*/
|
||||
static int mmrm_vm_be_client_register(struct mmrm_vm_driver_data *mmrm_vm,
|
||||
struct mmrm_vm_api_request_msg *req)
|
||||
{
|
||||
struct mmrm_client *pClient;
|
||||
int rc;
|
||||
struct mmrm_vm_response_msg_pkt pkt;
|
||||
struct mmrm_client_desc client_desc;
|
||||
|
||||
// unpacketizing the call from fe on SVM
|
||||
client_desc.client_type = req->data.reg.client_type;
|
||||
memcpy(&(client_desc.client_info.desc), &(req->data.reg.desc),
|
||||
sizeof(client_desc.client_info.desc));
|
||||
client_desc.priority = req->data.reg.priority;
|
||||
|
||||
d_mpr_l("%s: register type:%d priority:%d\n", __func__,
|
||||
client_desc.client_type, client_desc.priority);
|
||||
d_mpr_l("%s: domain:%d client ID:%d\n", __func__,
|
||||
client_desc.client_info.desc.client_domain,
|
||||
client_desc.client_info.desc.client_id);
|
||||
d_mpr_l("%s: clk name:%s\n", __func__, client_desc.client_info.desc.name);
|
||||
|
||||
// call mmrm register function
|
||||
pClient = mmrm_client_register(&client_desc);
|
||||
if (pClient != NULL) {
|
||||
mmrm_vm->clk_client_tbl[pClient->client_uid] = pClient;
|
||||
pkt.msg.data.reg.client_id = pClient->client_uid;
|
||||
} else {
|
||||
pkt.msg.data.reg.client_id = 0;
|
||||
d_mpr_e("%s: client:%p\n", __func__, pClient);
|
||||
}
|
||||
|
||||
// prepare response packet & send to fe on SVM
|
||||
pkt.msg.hd.cmd_id = MMRM_VM_RESPONSE_REGISTER;
|
||||
pkt.msg.hd.seq_no = req->hd.seq_no;
|
||||
pkt.hdr.size = sizeof(pkt.msg.hd) + sizeof(pkt.msg.data.reg);
|
||||
|
||||
d_mpr_l("%s: cmd_id:%d data size:%d\n", __func__, pkt.msg.hd.cmd_id, pkt.hdr.size);
|
||||
|
||||
rc = mmrm_vm_be_send_response(mmrm_vm, &pkt);
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: rc:%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_client_setvalue - call mmrm API to set client values
|
||||
* mmrm_vm: driver private data
|
||||
* req: set client value request parameters
|
||||
*/
|
||||
static int mmrm_vm_be_client_setvalue(struct mmrm_vm_driver_data *mmrm_vm,
|
||||
struct mmrm_vm_api_request_msg *req)
|
||||
{
|
||||
struct mmrm_vm_response_msg_pkt pkt_resp;
|
||||
int rc;
|
||||
struct mmrm_vm_setvalue_request *req_param = &req->data.setval;
|
||||
|
||||
// call mmrm client set value function, and fill response packet
|
||||
|
||||
rc = mmrm_client_set_value(mmrm_vm->clk_client_tbl[req_param->client_id],
|
||||
&req_param->data, req_param->val);
|
||||
|
||||
// prepare response packet & send to fe on SVM
|
||||
pkt_resp.msg.hd.cmd_id = MMRM_VM_RESPONSE_SETVALUE;
|
||||
pkt_resp.msg.hd.seq_no = req->hd.seq_no;
|
||||
pkt_resp.hdr.size = sizeof(pkt_resp.msg.hd) + sizeof(pkt_resp.msg.data.setval);
|
||||
|
||||
pkt_resp.msg.data.setval.val = rc;
|
||||
|
||||
d_mpr_l("%s: cmd_id:%d data size:%d\n", __func__,
|
||||
pkt_resp.msg.hd.cmd_id, pkt_resp.hdr.size);
|
||||
|
||||
rc = mmrm_vm_be_send_response(mmrm_vm, &pkt_resp);
|
||||
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: rc:%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_client_setvalue_inrange - call mmrm API to set client range values
|
||||
* mmrm_vm: driver private data
|
||||
* req: set client value request parameters
|
||||
*/
|
||||
static int mmrm_vm_be_client_setvalue_inrange(struct mmrm_vm_driver_data *mmrm_vm,
|
||||
struct mmrm_vm_api_request_msg *req)
|
||||
{
|
||||
struct mmrm_vm_response_msg_pkt pkt;
|
||||
int rc;
|
||||
struct mmrm_vm_setvalue_inrange_request *req_param = &req->data.setval_range;
|
||||
|
||||
rc = mmrm_client_set_value_in_range(mmrm_vm->clk_client_tbl[req_param->client_id],
|
||||
&req_param->data, &req_param->val);
|
||||
|
||||
pkt.msg.hd.cmd_id = MMRM_VM_RESPONSE_SETVALUE_INRANGE;
|
||||
pkt.msg.hd.seq_no = req->hd.seq_no;
|
||||
pkt.msg.data.setval_range.ret_code = rc;
|
||||
pkt.hdr.size = sizeof(pkt.msg.hd) + sizeof(pkt.msg.data.setval_range);
|
||||
|
||||
d_mpr_l("%s: cmd_id:%d data size:%d\n", __func__, pkt.msg.hd.cmd_id, pkt.hdr.size);
|
||||
|
||||
rc = mmrm_vm_be_send_response(mmrm_vm, &pkt);
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: rc:%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_client_getvalue - call mmrm API to get client values
|
||||
* mmrm_vm: driver private data
|
||||
* req: set client value request parameters
|
||||
*/
|
||||
static int mmrm_vm_be_client_getvalue(struct mmrm_vm_driver_data *mmrm_vm,
|
||||
struct mmrm_vm_api_request_msg *req)
|
||||
{
|
||||
struct mmrm_vm_response_msg_pkt pkt;
|
||||
int rc;
|
||||
struct mmrm_vm_getvalue_request *req_param = &req->data.getval;
|
||||
struct mmrm_client_res_value val;
|
||||
struct mmrm_client_res_value *p_val = &pkt.msg.data.getval.val;
|
||||
|
||||
rc = mmrm_client_get_value(mmrm_vm->clk_client_tbl[req_param->client_id], &val);
|
||||
|
||||
pkt.msg.hd.cmd_id = MMRM_VM_RESPONSE_GETVALUE;
|
||||
pkt.msg.hd.seq_no = req->hd.seq_no;
|
||||
pkt.hdr.size = sizeof(pkt.msg.hd) + sizeof(pkt.msg.data.getval);
|
||||
|
||||
p_val->cur = val.cur;
|
||||
p_val->max = val.max;
|
||||
p_val->min = val.min;
|
||||
|
||||
// pr_err("%s: cmd_id:%d data size:%d\n", __func__, pkt.msg.hd.cmd_id, pkt.hdr.size);
|
||||
|
||||
rc = mmrm_vm_be_send_response(mmrm_vm, &pkt);
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: rc:%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_client_deregister - call mmrm API to deregister client
|
||||
* mmrm_vm: driver private data
|
||||
* req: set client value request parameters
|
||||
*/
|
||||
static int mmrm_vm_be_client_deregister(struct mmrm_vm_driver_data *mmrm_vm,
|
||||
struct mmrm_vm_api_request_msg *req)
|
||||
{
|
||||
int rc;
|
||||
struct mmrm_vm_response_msg_pkt pkt;
|
||||
struct mmrm_vm_deregister_request *req_param = &req->data.dereg;
|
||||
|
||||
rc = mmrm_client_deregister(mmrm_vm->clk_client_tbl[req_param->client_id]);
|
||||
// pr_err("%s: client:%d\n", __func__, req_param->client_id);
|
||||
|
||||
pkt.msg.hd.cmd_id = MMRM_VM_RESPONSE_DEREGISTER;
|
||||
pkt.msg.hd.seq_no = req->hd.seq_no;
|
||||
|
||||
pkt.hdr.size = sizeof(pkt.msg.hd) + sizeof(pkt.msg.data.dereg);
|
||||
pkt.msg.data.dereg.ret_code = rc;
|
||||
|
||||
// pr_err("%s: cmd_id:%d data size:%d ret:%d\n", __func__,
|
||||
// pkt.msg.hd.cmd_id, pkt.hdr.size, pkt.msg.data.dereg.ret_code);
|
||||
|
||||
rc = mmrm_vm_be_send_response(mmrm_vm, &pkt);
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: rc:%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_recv - be dispatch mmrm request to mmrm API call
|
||||
* mmrm_vm: driver private data
|
||||
* data: request message buffer pointer
|
||||
* size: request message size
|
||||
*/
|
||||
int mmrm_vm_be_recv(struct mmrm_vm_driver_data *mmrm_vm, void *data, size_t size)
|
||||
{
|
||||
struct mmrm_vm_api_request_msg *cmd = data;
|
||||
int rc = -1;
|
||||
|
||||
switch (cmd->hd.cmd_id) {
|
||||
case MMRM_VM_REQUEST_REGISTER:
|
||||
rc = mmrm_vm_be_client_register(mmrm_vm, cmd);
|
||||
break;
|
||||
|
||||
case MMRM_VM_REQUEST_SETVALUE:
|
||||
rc = mmrm_vm_be_client_setvalue(mmrm_vm, cmd);
|
||||
break;
|
||||
|
||||
case MMRM_VM_REQUEST_SETVALUE_INRANGE:
|
||||
rc = mmrm_vm_be_client_setvalue_inrange(mmrm_vm, cmd);
|
||||
break;
|
||||
|
||||
case MMRM_VM_REQUEST_GETVALUE:
|
||||
rc = mmrm_vm_be_client_getvalue(mmrm_vm, cmd);
|
||||
break;
|
||||
|
||||
case MMRM_VM_REQUEST_DEREGISTER:
|
||||
rc = mmrm_vm_be_client_deregister(mmrm_vm, cmd);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: cmd_id:%d unknown!!!\n", __func__, cmd->hd.cmd_id);
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
115
vm/be/src/mmrm_vm_be_main.c
Normal file
115
vm/be/src/mmrm_vm_be_main.c
Normal file
@@ -0,0 +1,115 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "mmrm_vm_be.h"
|
||||
#include "mmrm_vm_msgq.h"
|
||||
#include "mmrm_vm_interface.h"
|
||||
#include "mmrm_debug.h"
|
||||
|
||||
#define MMRM_CLK_CLIENTS_NUM_MAX 35
|
||||
|
||||
struct mmrm_vm_driver_data *drv_vm_be = (void *) -EPROBE_DEFER;
|
||||
|
||||
int msm_mmrm_debug = MMRM_ERR | MMRM_WARN | MMRM_PRINTK;
|
||||
|
||||
int mmrm_client_get_clk_count(void);
|
||||
|
||||
static int mmrm_vm_be_driver_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int sz, clk_count, rc;
|
||||
|
||||
drv_vm_be = devm_kzalloc(dev, sizeof(*drv_vm_be), GFP_KERNEL);
|
||||
if (!drv_vm_be)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_count = mmrm_client_get_clk_count();
|
||||
if (clk_count <= 0 || clk_count > MMRM_CLK_CLIENTS_NUM_MAX) {
|
||||
d_mpr_e("%s: clk count is not correct\n", __func__);
|
||||
goto clk_count_err;
|
||||
}
|
||||
sz = sizeof(struct mmrm_client *) * clk_count;
|
||||
drv_vm_be->clk_client_tbl = devm_kzalloc(dev, sz, GFP_KERNEL);
|
||||
if (!drv_vm_be->clk_client_tbl)
|
||||
goto client_tbl_err;
|
||||
|
||||
drv_vm_be->debugfs_root = msm_mmrm_debugfs_init();
|
||||
if (!drv_vm_be->debugfs_root)
|
||||
d_mpr_e("%s: failed to create debugfs for mmrm\n", __func__);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, drv_vm_be);
|
||||
rc = mmrm_vm_msgq_init(drv_vm_be);
|
||||
if (rc != 0) {
|
||||
d_mpr_e("%s: failed to init msgq\n", __func__);
|
||||
goto msgq_init_err;
|
||||
}
|
||||
|
||||
dev_err(dev, "msgq probe success");
|
||||
return 0;
|
||||
|
||||
client_tbl_err:
|
||||
dev_err(dev, "msgq register alloc memory failed");
|
||||
return -ENOMEM;
|
||||
msgq_init_err:
|
||||
kfree(drv_vm_be->clk_client_tbl);
|
||||
msm_mmrm_debugfs_deinit(drv_vm_be->debugfs_root);
|
||||
mmrm_vm_msgq_deinit(drv_vm_be);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
clk_count_err:
|
||||
kfree(drv_vm_be);
|
||||
drv_vm_be = (void *) -EPROBE_DEFER;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int mmrm_vm_be_driver_remove(struct platform_device *pdev)
|
||||
{
|
||||
mmrm_vm_msgq_deinit(drv_vm_be);
|
||||
msm_mmrm_debugfs_deinit(drv_vm_be->debugfs_root);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
kfree(drv_vm_be);
|
||||
drv_vm_be = (void *) -EPROBE_DEFER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mmrm_vm_be_match[] = {
|
||||
{ .compatible = "qcom,mmrm-vm-be" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mmrm_vm_be_match);
|
||||
|
||||
static struct platform_driver mmrm_vm_be_driver = {
|
||||
.probe = mmrm_vm_be_driver_probe,
|
||||
.driver = {
|
||||
.name = "mmrm-vm-be",
|
||||
.of_match_table = mmrm_vm_be_match,
|
||||
},
|
||||
.remove = mmrm_vm_be_driver_remove,
|
||||
};
|
||||
|
||||
static int __init mmrm_vm_be_module_init(void)
|
||||
{
|
||||
pr_info("%s: init start\n", __func__);
|
||||
|
||||
return platform_driver_register(&mmrm_vm_be_driver);
|
||||
}
|
||||
subsys_initcall(mmrm_vm_be_module_init);
|
||||
|
||||
static void __exit mmrm_vm_be_module_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mmrm_vm_be_driver);
|
||||
}
|
||||
module_exit(mmrm_vm_be_module_exit);
|
||||
|
||||
MODULE_SOFTDEP("pre: gunyah_transport");
|
||||
MODULE_SOFTDEP("pre: msm-mmrm");
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. MMRM BE Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
274
vm/be/src/mmrm_vm_be_msgq.c
Normal file
274
vm/be/src/mmrm_vm_be_msgq.c
Normal file
@@ -0,0 +1,274 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/gunyah/gh_msgq.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/gunyah/gh_rm_drv.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "mmrm_vm_be.h"
|
||||
#include "mmrm_vm_interface.h"
|
||||
#include "mmrm_vm_debug.h"
|
||||
|
||||
#define MAX_ERR_COUNT 5
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_msg_handler - fe request handler
|
||||
* work: work parameter that workqueue thread transfer
|
||||
*/
|
||||
static void mmrm_vm_msgq_msg_handler(struct work_struct *work)
|
||||
{
|
||||
struct mmrm_vm_thread_info *pthread_info =
|
||||
container_of(work, struct mmrm_vm_thread_info, msgq_work.work);
|
||||
struct mmrm_vm_driver_data *mmrm_vm =
|
||||
container_of(pthread_info, struct mmrm_vm_driver_data, thread_info);
|
||||
struct mmrm_vm_msg *msg;
|
||||
struct mmrm_vm_msg *next_msg;
|
||||
struct list_head head;
|
||||
|
||||
if (IS_ERR_OR_NULL(work))
|
||||
return;
|
||||
|
||||
mutex_lock(&pthread_info->list_lock);
|
||||
list_replace_init(&pthread_info->queued_msg, &head);
|
||||
mutex_unlock(&pthread_info->list_lock);
|
||||
|
||||
list_for_each_entry_safe(msg, next_msg, &head, link) {
|
||||
mmrm_vm_be_recv(mmrm_vm, msg->msg_buf, msg->msg_size);
|
||||
list_del(&msg->link);
|
||||
kfree(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_msgq_listener - gunyah's message receiving thread
|
||||
* data: parameter that caller transfer
|
||||
*/
|
||||
static int mmrm_vm_be_msgq_listener(void *data)
|
||||
{
|
||||
struct mmrm_vm_driver_data *mmrm_vm;
|
||||
struct mmrm_vm_gh_msgq_info *pmsg_info;
|
||||
struct mmrm_vm_thread_info *thread_info;
|
||||
|
||||
struct mmrm_vm_msg *msg;
|
||||
size_t size;
|
||||
int ret = 0;
|
||||
int err_count = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(data))
|
||||
return -EINVAL;
|
||||
|
||||
mmrm_vm = (struct mmrm_vm_driver_data *)data;
|
||||
pmsg_info = &mmrm_vm->msg_info;
|
||||
thread_info = &mmrm_vm->thread_info;
|
||||
|
||||
while (true) {
|
||||
msg = kzalloc(sizeof(struct mmrm_vm_msg), GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = gh_msgq_recv(pmsg_info->msgq_handle, msg->msg_buf,
|
||||
GH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0);
|
||||
if (ret < 0) {
|
||||
kfree(msg);
|
||||
d_mpr_e("gh_msgq_recv failed, rc=%d\n", ret);
|
||||
err_count++;
|
||||
if (err_count < MAX_ERR_COUNT)
|
||||
continue;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err_count = 0;
|
||||
msg->msg_size = size;
|
||||
|
||||
mutex_lock(&thread_info->list_lock);
|
||||
list_add_tail(&thread_info->queued_msg, &msg->link);
|
||||
mutex_unlock(&thread_info->list_lock);
|
||||
|
||||
queue_delayed_work(thread_info->msg_workq,
|
||||
&thread_info->msgq_work, msecs_to_jiffies(0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_send - send response message by gunyah API
|
||||
* mmrm_vm: driver data
|
||||
* msg: message buffer pointer
|
||||
* msg_size: message size
|
||||
*/
|
||||
int mmrm_vm_msgq_send(struct mmrm_vm_driver_data *mmrm_vm, void *msg, size_t msg_size)
|
||||
{
|
||||
if (!mmrm_vm->msg_info.msgq_handle) {
|
||||
d_mpr_e("Failed to send msg, invalid msgq handle\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msg_size > GH_MSGQ_MAX_MSG_SIZE_BYTES) {
|
||||
d_mpr_e("msg size unsupported for msgq: %ld > %d\n", msg_size,
|
||||
GH_MSGQ_MAX_MSG_SIZE_BYTES);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
return gh_msgq_send(mmrm_vm->msg_info.msgq_handle, msg, msg_size, GH_MSGQ_TX_PUSH);
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_gh_validate_register - check gunyah connection validation
|
||||
* msg_info: gunyah meesage info
|
||||
* vm_status_payload: gunyah notification message status info
|
||||
*/
|
||||
int mmrm_vm_be_gh_validate_register(struct mmrm_vm_gh_msgq_info *msg_info,
|
||||
struct gh_rm_notif_vm_status_payload *vm_status_payload)
|
||||
{
|
||||
gh_vmid_t peer_vmid;
|
||||
gh_vmid_t self_vmid;
|
||||
int rc = -1;
|
||||
|
||||
if (vm_status_payload->vm_status != GH_RM_VM_STATUS_READY)
|
||||
return rc;
|
||||
|
||||
d_mpr_l("%s: status=%d\n", __func__, vm_status_payload->vm_status);
|
||||
if (gh_rm_get_vmid(msg_info->peer_id, &peer_vmid))
|
||||
return rc;
|
||||
|
||||
if (gh_rm_get_vmid(GH_PRIMARY_VM, &self_vmid))
|
||||
return rc;
|
||||
|
||||
if (peer_vmid != vm_status_payload->vmid)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
d_mpr_l("%s: vmid=%d peer_vmid=%d\n", __func__, vm_status_payload->vmid, peer_vmid);
|
||||
|
||||
if (msg_info->msgq_handle) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
msg_info->msgq_handle = gh_msgq_register(msg_info->msgq_label);
|
||||
|
||||
d_mpr_l("%s: label=%d\n", __func__, msg_info->msgq_label);
|
||||
rc = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(msg_info->msgq_handle)) {
|
||||
rc = -1;
|
||||
d_mpr_e("%s: gunyah message queue registration failed\n", __func__);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_be_msgq_cb - check gunyah connection validation
|
||||
* nb: gunyah notofier block info
|
||||
* cmd: gunyah notification status category info
|
||||
* data: user defined data pointer
|
||||
*/
|
||||
static int mmrm_vm_be_msgq_cb(struct notifier_block *nb, unsigned long cmd, void *data)
|
||||
{
|
||||
struct gh_rm_notif_vm_status_payload *vm_status_payload;
|
||||
struct mmrm_vm_driver_data *mmrm_vm;
|
||||
struct mmrm_vm_gh_msgq_info *msg_info;
|
||||
struct mmrm_vm_thread_info *thread_info;
|
||||
int rc;
|
||||
|
||||
if (IS_ERR_OR_NULL(nb))
|
||||
return -EINVAL;
|
||||
|
||||
msg_info = container_of(nb, struct mmrm_vm_gh_msgq_info, pvt_nb);
|
||||
mmrm_vm = container_of(msg_info, struct mmrm_vm_driver_data, msg_info);
|
||||
|
||||
thread_info = &mmrm_vm->thread_info;
|
||||
if (cmd != GH_RM_NOTIF_VM_STATUS)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
/*
|
||||
* check VM status, only GH_TRUSTED_VM notification activate
|
||||
* GUNYAH message queue registering
|
||||
*/
|
||||
vm_status_payload = (struct gh_rm_notif_vm_status_payload *)data;
|
||||
rc = mmrm_vm_be_gh_validate_register(msg_info, vm_status_payload);
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: msgq registration failed: err:%d\n",
|
||||
__func__, PTR_ERR(msg_info->msgq_handle));
|
||||
|
||||
thread_info->msgq_listener_thread = kthread_run(mmrm_vm_be_msgq_listener,
|
||||
(void *)mmrm_vm, "mmrm_msgq_listener");
|
||||
if (IS_ERR_OR_NULL(thread_info->msgq_listener_thread)) {
|
||||
return NOTIFY_DONE;
|
||||
};
|
||||
|
||||
wake_up_process(thread_info->msgq_listener_thread);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_init - gunyah message queue initialization
|
||||
* mmrm_vm: driver data
|
||||
*/
|
||||
int mmrm_vm_msgq_init(struct mmrm_vm_driver_data *mmrm_vm)
|
||||
{
|
||||
struct mmrm_vm_gh_msgq_info *msg_info;
|
||||
struct mmrm_vm_thread_info *thread_info;
|
||||
int rc;
|
||||
|
||||
if (IS_ERR_OR_NULL(mmrm_vm))
|
||||
return -EINVAL;
|
||||
|
||||
msg_info = &mmrm_vm->msg_info;
|
||||
thread_info = &mmrm_vm->thread_info;
|
||||
|
||||
msg_info->msgq_label = GH_MSGQ_LABEL_MMRM;
|
||||
d_mpr_l("%s: msgq-label=%d\n", __func__, msg_info->msgq_label);
|
||||
|
||||
msg_info->peer_id = GH_TRUSTED_VM;
|
||||
msg_info->pvt_nb.notifier_call = mmrm_vm_be_msgq_cb;
|
||||
rc = gh_rm_register_notifier(&msg_info->pvt_nb);
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
|
||||
mutex_init(&thread_info->list_lock);
|
||||
INIT_LIST_HEAD(&thread_info->queued_msg);
|
||||
thread_info->msg_workq = create_singlethread_workqueue("vm_message_workq");
|
||||
if (IS_ERR_OR_NULL(thread_info->msg_workq)) {
|
||||
return -1;
|
||||
};
|
||||
INIT_DELAYED_WORK(&thread_info->msgq_work, mmrm_vm_msgq_msg_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_init - gunyah message queue de-initialization
|
||||
* mmrm_vm: driver data
|
||||
*/
|
||||
int mmrm_vm_msgq_deinit(struct mmrm_vm_driver_data *mmrm_vm)
|
||||
{
|
||||
struct mmrm_vm_gh_msgq_info *msg_info;
|
||||
struct mmrm_vm_thread_info *thread_info;
|
||||
int rc = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(mmrm_vm))
|
||||
return -EINVAL;
|
||||
|
||||
msg_info = &mmrm_vm->msg_info;
|
||||
thread_info = &mmrm_vm->thread_info;
|
||||
if (thread_info->msgq_listener_thread)
|
||||
kthread_stop(thread_info->msgq_listener_thread);
|
||||
|
||||
gh_rm_unregister_notifier(&msg_info->pvt_nb);
|
||||
|
||||
if (msg_info->msgq_handle) {
|
||||
rc = gh_msgq_unregister(msg_info->msgq_handle);
|
||||
if (rc != 0)
|
||||
d_mpr_e("%s: msgq unregistration failed: err:%d\n", __func__, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
63
vm/common/inc/mmrm_vm_debug.h
Normal file
63
vm/common/inc/mmrm_vm_debug.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MMRM_VM_DEBUG__
|
||||
#define __MMRM_VM_DEBUG__
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
#ifndef MMRM_VM_DBG_LABEL
|
||||
#define MMRM_VM_DBG_LABEL "mmrm_vm"
|
||||
#endif
|
||||
|
||||
#define MMRM_VM_DBG_TAG MMRM_VM_DBG_LABEL ": %4s: "
|
||||
|
||||
/* To enable messages OR these values and
|
||||
* echo the result to debugfs file.
|
||||
*/
|
||||
enum mmrm_msg_prio {
|
||||
MMRM_VM_ERR = 0x000001,
|
||||
MMRM_VM_HIGH = 0x000002,
|
||||
MMRM_VM_LOW = 0x000004,
|
||||
MMRM_VM_WARN = 0x000008,
|
||||
MMRM_VM_PRINTK = 0x010000,
|
||||
};
|
||||
|
||||
extern int mmrm_vm_debug;
|
||||
|
||||
#define dprintk(__level, __fmt, ...) \
|
||||
do { \
|
||||
if (mmrm_vm_debug & __level) { \
|
||||
if (mmrm_vm_debug & MMRM_VM_PRINTK) { \
|
||||
pr_info(MMRM_VM_DBG_TAG __fmt, \
|
||||
get_debug_level_str(__level), \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define d_mpr_e(__fmt, ...) dprintk(MMRM_VM_ERR, __fmt, ##__VA_ARGS__)
|
||||
#define d_mpr_h(__fmt, ...) dprintk(MMRM_VM_HIGH, __fmt, ##__VA_ARGS__)
|
||||
#define d_mpr_l(__fmt, ...) dprintk(MMRM_VM_LOW, __fmt, ##__VA_ARGS__)
|
||||
#define d_mpr_w(__fmt, ...) dprintk(MMRM_VM_WARN, __fmt, ##__VA_ARGS__)
|
||||
|
||||
static inline char *get_debug_level_str(int level)
|
||||
{
|
||||
switch (level) {
|
||||
case MMRM_VM_ERR:
|
||||
return "err ";
|
||||
case MMRM_VM_HIGH:
|
||||
return "high";
|
||||
case MMRM_VM_LOW:
|
||||
return "low ";
|
||||
case MMRM_VM_WARN:
|
||||
return "warn";
|
||||
default:
|
||||
return "????";
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __MMRM_VM_DEBUG__ */
|
222
vm/common/inc/mmrm_vm_interface.h
Normal file
222
vm/common/inc/mmrm_vm_interface.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MMRM_VM_INTERNAL_H__
|
||||
#define __MMRM_VM_INTERNAL_H__
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/soc/qcom/msm_mmrm.h>
|
||||
|
||||
#include <mmrm_vm_msgq.h>
|
||||
|
||||
/**
|
||||
* mmrm_vm_thread_info - message listener & workqueue info
|
||||
* @msgq_listener_thread: handle to msgq listener thread that is used
|
||||
* to receive/send messages through gunyah interface
|
||||
* @msg_workq: message workqueue pointer
|
||||
* @msgq_work: message work, worker thread to process the messages
|
||||
* @queued_msg: message queue head
|
||||
*/
|
||||
struct mmrm_vm_thread_info {
|
||||
struct task_struct *msgq_listener_thread;
|
||||
struct workqueue_struct *msg_workq;
|
||||
struct delayed_work msgq_work;
|
||||
struct mutex list_lock;
|
||||
struct list_head queued_msg;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_data_priv -- device driver private part
|
||||
* @msg_info: gunyah message info
|
||||
* @thread_info: message lister & workqueue info
|
||||
* @clk_client_tbl: index and client handler LUT
|
||||
* @debugfs_root: debug fs, /sys/kernel/debug
|
||||
* @vm_pvt_data: pointer to fe/be specific data
|
||||
*/
|
||||
struct mmrm_vm_driver_data {
|
||||
struct mmrm_vm_gh_msgq_info msg_info;
|
||||
struct mmrm_vm_thread_info thread_info;
|
||||
struct mmrm_client **clk_client_tbl;
|
||||
|
||||
/* debugfs */
|
||||
struct dentry *debugfs_root;
|
||||
void *vm_pvt_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* enum mmrm_vm_api_msg_id -- request/response cmd ID
|
||||
*/
|
||||
enum mmrm_vm_api_msg_id {
|
||||
MMRM_VM_REQUEST_REGISTER = 1,
|
||||
MMRM_VM_REQUEST_SETVALUE,
|
||||
MMRM_VM_REQUEST_SETVALUE_INRANGE,
|
||||
MMRM_VM_REQUEST_GETVALUE,
|
||||
MMRM_VM_REQUEST_DEREGISTER,
|
||||
|
||||
MMRM_VM_RESPONSE_REGISTER = MMRM_VM_REQUEST_REGISTER | 0x800,
|
||||
MMRM_VM_RESPONSE_SETVALUE,
|
||||
MMRM_VM_RESPONSE_SETVALUE_INRANGE,
|
||||
MMRM_VM_RESPONSE_GETVALUE,
|
||||
MMRM_VM_RESPONSE_DEREGISTER,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct msg_head -- message head
|
||||
* @cmd_id: mmrm API message cmd id
|
||||
* @seq_no: message sequence id
|
||||
*/
|
||||
struct mmrm_vm_api_msg_head {
|
||||
enum mmrm_vm_api_msg_id cmd_id;
|
||||
int seq_no;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct register_request -- mmrm register parameters
|
||||
* @client_type: client type, definition see msm_mmrm.h
|
||||
* @priority: client priority, definition see msm_mmrm.h
|
||||
* @desc: client description, definition see msm_mmrm.h
|
||||
*/
|
||||
struct mmrm_vm_register_request {
|
||||
enum mmrm_client_type client_type;
|
||||
enum mmrm_client_priority priority;
|
||||
struct mmrm_clk_client_desc desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct deregister_request -- mmrm deregister parameters
|
||||
* @client: client registered handle
|
||||
*/
|
||||
struct mmrm_vm_deregister_request {
|
||||
u32 client_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct setvalue_request -- mmrm setvalue parameters
|
||||
* @client: client type, definition see msm_mmrm.h
|
||||
* @data: client info, definition see msm_mmrm.h
|
||||
* @val: new clock rate value
|
||||
*/
|
||||
struct mmrm_vm_setvalue_request {
|
||||
u32 client_id;
|
||||
struct mmrm_client_data data;
|
||||
unsigned long val;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_setvalue_inrange_request -- mmrm setvalue_inrange parameters
|
||||
* @client: client type, definition see msm_mmrm.h
|
||||
* @data: client info, definition see msm_mmrm.h
|
||||
* @val: new clock rate value range, definition see msm_mmrm.h
|
||||
*/
|
||||
struct mmrm_vm_setvalue_inrange_request {
|
||||
u32 client_id;
|
||||
struct mmrm_client_data data;
|
||||
struct mmrm_client_res_value val;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_getvalue_request -- mmrm getvalue parameters
|
||||
* @client: client type, definition see msm_mmrm.h
|
||||
* @val: current clock rate value range, definition see msm_mmrm.h
|
||||
*/
|
||||
struct mmrm_vm_getvalue_request {
|
||||
u32 client_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_api_request_msg -- mmrm request API message unified data definition
|
||||
* @hd: mmrm API request message head
|
||||
* @data: parameters mmrm API needs per API message cmd id
|
||||
*/
|
||||
struct mmrm_vm_api_request_msg {
|
||||
struct mmrm_vm_api_msg_head hd;
|
||||
union {
|
||||
struct mmrm_vm_register_request reg;
|
||||
struct mmrm_vm_deregister_request dereg;
|
||||
struct mmrm_vm_setvalue_request setval;
|
||||
struct mmrm_vm_setvalue_inrange_request setval_range;
|
||||
struct mmrm_vm_getvalue_request getval;
|
||||
} data;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_register_response -- mmrm_client_register API response message
|
||||
* @client: handle for registered client
|
||||
*/
|
||||
struct mmrm_vm_register_response {
|
||||
u32 client_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_deregister_response -- mmrm_client_deregister API response message
|
||||
* @ret_code: indicates if the mmrm_client_deregister is successful
|
||||
*/
|
||||
struct mmrm_vm_deregister_response {
|
||||
int ret_code;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_setvalue_response -- mmrm_client_set_value API response message
|
||||
* @val: value that mmrm_client_set_value return
|
||||
*/
|
||||
struct mmrm_vm_setvalue_response {
|
||||
unsigned long val;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_setvalue_inrange_response -- mmrm_client_set_value_in_range API response message
|
||||
* @ret_code: value that mmrm_client_set_value_in_range return
|
||||
*/
|
||||
struct mmrm_vm_setvalue_inrange_response {
|
||||
int ret_code;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_getvalue_response -- mmrm_client_get_value API response message
|
||||
* @val: value that mmrm_client_get_value return
|
||||
*/
|
||||
struct mmrm_vm_getvalue_response {
|
||||
struct mmrm_client_res_value val;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_api_response_msg -- mmrm response message unified data
|
||||
* @hd: mmrm API response message head
|
||||
* @data: data that mmrm API return per API response message id
|
||||
*/
|
||||
struct mmrm_vm_api_response_msg {
|
||||
struct mmrm_vm_api_msg_head hd;
|
||||
union {
|
||||
struct mmrm_vm_register_response reg;
|
||||
struct mmrm_vm_deregister_response dereg;
|
||||
struct mmrm_vm_setvalue_response setval;
|
||||
struct mmrm_vm_setvalue_inrange_response setval_range;
|
||||
struct mmrm_vm_getvalue_response getval;
|
||||
} data;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_request_msg_pkt -- mmrm request packet that is sent through gunyah API
|
||||
* @hdr: message head for checking message valid
|
||||
* @msg: data that is needed by mmrm API
|
||||
*/
|
||||
struct mmrm_vm_request_msg_pkt {
|
||||
struct mmrm_vm_msg_hdr hdr;
|
||||
struct mmrm_vm_api_request_msg msg;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mmrm_vm_response_msg_pkt -- mmrm response packet that is sent through gunyah API
|
||||
* @hdr: message head for checking message valid
|
||||
* @msg: data that is returned by mmrm API
|
||||
*/
|
||||
struct mmrm_vm_response_msg_pkt {
|
||||
struct mmrm_vm_msg_hdr hdr;
|
||||
struct mmrm_vm_api_response_msg msg;
|
||||
};
|
||||
|
||||
#endif /* __MMRM_VM_INTERNAL_H__ */
|
||||
|
||||
|
99
vm/common/inc/mmrm_vm_msgq.h
Normal file
99
vm/common/inc/mmrm_vm_msgq.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MMRM_VM_MSGQ_H__
|
||||
#define __MMRM_VM_MSGQ_H__
|
||||
|
||||
#include <linux/gunyah/gh_msgq.h>
|
||||
|
||||
#define MMRM_VM_VER_1 1 // mmrm version, for message valid check
|
||||
|
||||
#define MMRM_VM_MAX_PKT_SZ 1024 // mmrm max gunyah packet size
|
||||
|
||||
/* mmrm_vm_pkt_type: mmrm transfer type, for message valid check
|
||||
* @MMRM_VM_TYPE_DATA: request/response data
|
||||
*/
|
||||
enum mmrm_vm_pkt_type {
|
||||
MMRM_VM_TYPE_DATA = 1,
|
||||
};
|
||||
|
||||
struct mmrm_vm_driver_data;
|
||||
|
||||
/**
|
||||
* struct mmrm_vm_msg_hdr - mmrm vm packet header
|
||||
* @version: protocol version
|
||||
* @type: packet type; one of MMRM_VM_TYPE_* in mmrm_vm_pkt_type
|
||||
* @flags: Reserved for future use
|
||||
* @size: length of packet, excluding this header
|
||||
*/
|
||||
struct mmrm_vm_msg_hdr {
|
||||
u8 version;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
u8 resv;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
/**
|
||||
* mmrm_vm_msg - message that be received.
|
||||
* @link - list head
|
||||
* @msg_size - message size
|
||||
* @msg_buf - message buffer
|
||||
*/
|
||||
struct mmrm_vm_msg {
|
||||
struct list_head link;
|
||||
size_t msg_size;
|
||||
unsigned char msg_buf[GH_MSGQ_MAX_MSG_SIZE_BYTES];
|
||||
};
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_info - gunyah info.
|
||||
* @peer_id: notification callback check if message is from SVM
|
||||
* @msgq_handle - registered msg queue handle with gunyah api
|
||||
* @msgq_label - message queue label
|
||||
* @pvt_nb - notifier info
|
||||
*/
|
||||
struct mmrm_vm_gh_msgq_info {
|
||||
int peer_id;
|
||||
void *msgq_handle;
|
||||
int msgq_label;
|
||||
struct notifier_block pvt_nb;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mmrm_vm_msg_q -- svm mmrm API caller queue that wait for mmrm API return
|
||||
* @link: list head
|
||||
* @m_req: request message pointer
|
||||
* @m_resp: response message buffer pointer
|
||||
* @complete: sync mmrm API response and caller
|
||||
*/
|
||||
struct mmrm_vm_msg_q {
|
||||
struct list_head link;
|
||||
struct mmrm_vm_request_msg_pkt *m_req;
|
||||
struct mmrm_vm_response_msg_pkt *m_resp;
|
||||
struct completion complete;
|
||||
};
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_init - initialize display message queue: both TX and RX
|
||||
* @mmrm_vm - handle to mmrm_vm_data_priv
|
||||
*/
|
||||
int mmrm_vm_msgq_init(struct mmrm_vm_driver_data *mmrm_vm);
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_deinit - deinitialize display message queue: both TX and RX
|
||||
* @mmrm_vm - handle to mmrm_vm_data_priv
|
||||
*/
|
||||
int mmrm_vm_msgq_deinit(struct mmrm_vm_driver_data *mmrm_vm);
|
||||
|
||||
/**
|
||||
* mmrm_vm_msgq_send - send custom messages across VM's
|
||||
* @mmrm_vm - handle to mmrm_vm_data_priv
|
||||
* @msg - payload data
|
||||
* @msg_size - size of the payload_data
|
||||
*/
|
||||
int mmrm_vm_msgq_send(struct mmrm_vm_driver_data *mmrm_vm, void *msg, size_t msg_size);
|
||||
#endif // __MMRM_VM_MSGQ_H__
|
||||
|
44
vm/common/src/mmrm_vm_debug.c
Normal file
44
vm/common/src/mmrm_vm_debug.c
Normal file
@@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "mmrm_vm_debug.h"
|
||||
|
||||
int mmrm_vm_debug = MMRM_VM_ERR | MMRM_VM_WARN | MMRM_VM_PRINTK;
|
||||
|
||||
/**
|
||||
* msm_mmrm_debugfs_init - init debug sys entry
|
||||
*/
|
||||
struct dentry *msm_mmrm_debugfs_init(void)
|
||||
{
|
||||
struct dentry *dir;
|
||||
|
||||
/* create a directory in debugfs root (/sys/kernel/debug) */
|
||||
dir = debugfs_create_dir("mmrm_vm", NULL);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
d_mpr_e("%s: Call to debugfs_create_dir(%s) failed!\n", __func__, "mmrm");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
/* add other params here */
|
||||
debugfs_create_u32("debug_level", 0644, dir, &mmrm_vm_debug);
|
||||
|
||||
return dir;
|
||||
|
||||
failed_create_dir:
|
||||
d_mpr_e("%s: error\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_mmrm_debugfs_deinit - de-init debug sys entry
|
||||
* dir: directory in debugfs root
|
||||
*/
|
||||
void msm_mmrm_debugfs_deinit(struct dentry *dir)
|
||||
{
|
||||
debugfs_remove_recursive(dir);
|
||||
}
|
||||
|
Reference in New Issue
Block a user