soc: hab: recycle mmid from qcpe to video
Add new mmid for video and other minor logging and efficiency fixes. Change-Id: I0ebbfadff76e7efb7f9afff9896dadf1bd8df9a1 Signed-off-by: Shiju Mathew <shijum@codeaurora.org>
This commit is contained in:
parent
2592658a93
commit
23beddbfdf
8 changed files with 155 additions and 53 deletions
|
@ -21,7 +21,7 @@
|
|||
.openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\
|
||||
}
|
||||
|
||||
static const char hab_info_str[] = "Change: 16764735 Revision: #76";
|
||||
static const char hab_info_str[] = "Change: 17280941 Revision: #81";
|
||||
|
||||
/*
|
||||
* The following has to match habmm definitions, order does not matter if
|
||||
|
@ -42,15 +42,13 @@ static struct hab_device hab_devices[] = {
|
|||
HAB_DEVICE_CNSTR(DEVICE_DISP5_NAME, MM_DISP_5, 10),
|
||||
HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 11),
|
||||
HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 12),
|
||||
HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 13),
|
||||
HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 14),
|
||||
HAB_DEVICE_CNSTR(DEVICE_QCPE2_NAME, MM_QCPE_VM2, 15),
|
||||
HAB_DEVICE_CNSTR(DEVICE_QCPE3_NAME, MM_QCPE_VM3, 16),
|
||||
HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 17),
|
||||
HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 18),
|
||||
HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 19),
|
||||
HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 20),
|
||||
HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 21),
|
||||
HAB_DEVICE_CNSTR(DEVICE_VID2_NAME, MM_VID_2, 13),
|
||||
HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 14),
|
||||
HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 15),
|
||||
HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 16),
|
||||
HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 17),
|
||||
HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 18),
|
||||
HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 19),
|
||||
};
|
||||
|
||||
struct hab_driver hab_driver = {
|
||||
|
@ -1082,15 +1080,25 @@ static int hab_release(struct inode *inodep, struct file *filep)
|
|||
/* notify remote side on vchan closing */
|
||||
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
|
||||
list_del(&vchan->node); /* vchan is not in this ctx anymore */
|
||||
hab_vchan_stop_notify(vchan);
|
||||
|
||||
if (!vchan->closed) { /* locally hasn't closed yet */
|
||||
if (!kref_get_unless_zero(&vchan->refcount)) {
|
||||
pr_err("vchan %x %x refcnt %d mismanaged closed %d remote closed %d\n",
|
||||
vchan->id,
|
||||
vchan->otherend_id,
|
||||
get_refcnt(vchan->refcount),
|
||||
vchan->closed, vchan->otherend_closed);
|
||||
continue; /* vchan is already being freed */
|
||||
} else {
|
||||
hab_vchan_stop_notify(vchan);
|
||||
/* put for notify. shouldn't cause free */
|
||||
hab_vchan_put(vchan);
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
|
||||
write_unlock(&ctx->ctx_lock);
|
||||
if (!vchan->closed) {
|
||||
pr_warn("potential leak vc %pK %x remote %x session %d refcnt %d\n",
|
||||
vchan, vchan->id, vchan->otherend_id,
|
||||
vchan->session_id,
|
||||
get_refcnt(vchan->refcount));
|
||||
hab_vchan_put(vchan); /* there is a lock inside */
|
||||
}
|
||||
hab_vchan_put(vchan); /* there is a lock inside */
|
||||
write_lock(&ctx->ctx_lock);
|
||||
}
|
||||
|
||||
|
@ -1324,7 +1332,6 @@ static int __init hab_init(void)
|
|||
dev_t dev;
|
||||
|
||||
place_marker("M - HAB INIT Start");
|
||||
|
||||
result = alloc_chrdev_region(&hab_driver.major, 0, 1, "hab");
|
||||
|
||||
if (result < 0) {
|
||||
|
@ -1379,11 +1386,8 @@ static int __init hab_init(void)
|
|||
} else
|
||||
set_dma_ops(hab_driver.dev, &hab_dma_ops);
|
||||
}
|
||||
|
||||
hab_stat_init(&hab_driver);
|
||||
|
||||
place_marker("M - HAB INIT End");
|
||||
|
||||
return result;
|
||||
|
||||
err:
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <linux/reboot.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <soc/qcom/boot_stats.h>
|
||||
|
||||
enum hab_payload_type {
|
||||
|
@ -81,11 +82,9 @@ enum hab_payload_type {
|
|||
#define DEVICE_DISP5_NAME "hab_disp5"
|
||||
#define DEVICE_GFX_NAME "hab_ogles"
|
||||
#define DEVICE_VID_NAME "hab_vid"
|
||||
#define DEVICE_VID2_NAME "hab_vid2"
|
||||
#define DEVICE_MISC_NAME "hab_misc"
|
||||
#define DEVICE_QCPE1_NAME "hab_qcpe_vm1"
|
||||
#define DEVICE_QCPE2_NAME "hab_qcpe_vm2"
|
||||
#define DEVICE_QCPE3_NAME "hab_qcpe_vm3"
|
||||
#define DEVICE_QCPE4_NAME "hab_qcpe_vm4"
|
||||
#define DEVICE_CLK1_NAME "hab_clock_vm1"
|
||||
#define DEVICE_CLK2_NAME "hab_clock_vm2"
|
||||
#define DEVICE_FDE1_NAME "hab_fde1"
|
||||
|
@ -346,6 +345,8 @@ struct hab_driver {
|
|||
};
|
||||
|
||||
struct virtual_channel {
|
||||
struct list_head node; /* for ctx */
|
||||
struct list_head pnode; /* for pchan */
|
||||
/*
|
||||
* refcount is used to track the references from hab core to the virtual
|
||||
* channel such as references from physical channels,
|
||||
|
@ -354,8 +355,6 @@ struct virtual_channel {
|
|||
struct kref refcount;
|
||||
struct physical_channel *pchan;
|
||||
struct uhab_context *ctx;
|
||||
struct list_head node; /* for ctx */
|
||||
struct list_head pnode; /* for pchan */
|
||||
struct list_head rx_list;
|
||||
wait_queue_head_t rx_queue;
|
||||
spinlock_t rx_lock;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "hab.h"
|
||||
#include "hab_ghs.h"
|
||||
|
||||
#define GIPC_VM_SET_CNT 22
|
||||
static const char * const dt_gipc_path_name[] = {
|
||||
"testgipc1",
|
||||
"testgipc2",
|
||||
|
@ -39,12 +40,41 @@ static const char * const dt_gipc_path_name[] = {
|
|||
"testgipc22",
|
||||
};
|
||||
|
||||
|
||||
/* same vmid assignment for all the vms. it should matches dt_gipc_path_name */
|
||||
int mmid_order[GIPC_VM_SET_CNT] = {
|
||||
MM_AUD_1,
|
||||
MM_AUD_2,
|
||||
MM_AUD_3,
|
||||
MM_AUD_4,
|
||||
MM_CAM_1,
|
||||
MM_CAM_2,
|
||||
MM_DISP_1,
|
||||
MM_DISP_2,
|
||||
MM_DISP_3,
|
||||
MM_DISP_4,
|
||||
MM_DISP_5,
|
||||
MM_GFX,
|
||||
MM_VID,
|
||||
MM_MISC,
|
||||
MM_QCPE_VM1,
|
||||
MM_VID_2, /* newly recycled */
|
||||
0,
|
||||
0,
|
||||
MM_CLK_VM1,
|
||||
MM_CLK_VM2,
|
||||
MM_FDE_1,
|
||||
MM_BUFFERQ_1,
|
||||
};
|
||||
|
||||
static struct ghs_vmm_plugin_info_s {
|
||||
const char * const *dt_name;
|
||||
int *mmid_dt_mapping;
|
||||
int curr;
|
||||
int probe_cnt;
|
||||
} ghs_vmm_plugin_info = {
|
||||
dt_gipc_path_name,
|
||||
mmid_order,
|
||||
0,
|
||||
ARRAY_SIZE(dt_gipc_path_name),
|
||||
};
|
||||
|
@ -59,6 +89,33 @@ static void ghs_irq_handler(void *cookie)
|
|||
tasklet_schedule(&dev->task);
|
||||
}
|
||||
|
||||
static int get_dt_name_idx(int vmid_base, int mmid,
|
||||
struct ghs_vmm_plugin_info_s *plugin_info)
|
||||
{
|
||||
int idx = -1;
|
||||
int i;
|
||||
|
||||
if (vmid_base < 0 || vmid_base > plugin_info->probe_cnt /
|
||||
GIPC_VM_SET_CNT) {
|
||||
pr_err("vmid %d overflow expected max %d\n", vmid_base,
|
||||
plugin_info->probe_cnt / GIPC_VM_SET_CNT);
|
||||
return idx;
|
||||
}
|
||||
|
||||
for (i = 0; i < GIPC_VM_SET_CNT; i++) {
|
||||
if (mmid == plugin_info->mmid_dt_mapping[i]) {
|
||||
idx = vmid_base * GIPC_VM_SET_CNT + i;
|
||||
if (idx > plugin_info->probe_cnt) {
|
||||
pr_err("dt name idx %d overflow max %d\n",
|
||||
idx, plugin_info->probe_cnt);
|
||||
idx = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* static struct physical_channel *habhyp_commdev_alloc(int id) */
|
||||
int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
|
||||
struct hab_device *mmid_device)
|
||||
|
@ -67,6 +124,7 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
|
|||
struct physical_channel *pchan = NULL;
|
||||
struct physical_channel **ppchan = (struct physical_channel **)commdev;
|
||||
int ret = 0;
|
||||
int dt_name_idx = 0;
|
||||
|
||||
if (ghs_vmm_plugin_info.curr > ghs_vmm_plugin_info.probe_cnt) {
|
||||
pr_err("too many commdev alloc %d, supported is %d\n",
|
||||
|
@ -101,13 +159,25 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
|
|||
gvh_dn = of_find_node_by_path("/aliases");
|
||||
if (gvh_dn) {
|
||||
const char *ep_path = NULL;
|
||||
struct device_node *ep_dn;
|
||||
struct device_node *ep_dn = NULL;
|
||||
|
||||
dt_name_idx = get_dt_name_idx(vmid_remote,
|
||||
mmid_device->id,
|
||||
&ghs_vmm_plugin_info);
|
||||
if (dt_name_idx < 0) {
|
||||
pr_err("failed to find %s for vmid %d ret %d\n",
|
||||
mmid_device->name,
|
||||
mmid_device->id,
|
||||
dt_name_idx);
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = of_property_read_string(gvh_dn,
|
||||
ghs_vmm_plugin_info.dt_name[ghs_vmm_plugin_info.curr],
|
||||
&ep_path);
|
||||
ghs_vmm_plugin_info.dt_name[dt_name_idx],
|
||||
&ep_path);
|
||||
if (ret)
|
||||
pr_err("failed to read endpoint string ret %d\n",
|
||||
pr_err("failed to read endpoint str ret %d\n",
|
||||
ret);
|
||||
of_node_put(gvh_dn);
|
||||
|
||||
|
@ -117,22 +187,23 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
|
|||
of_node_put(ep_dn);
|
||||
if (IS_ERR(dev->endpoint)) {
|
||||
ret = PTR_ERR(dev->endpoint);
|
||||
pr_err("KGIPC alloc failed id: %d, ret: %d\n",
|
||||
ghs_vmm_plugin_info.curr, ret);
|
||||
pr_err("alloc failed %d %s ret %d\n",
|
||||
dt_name_idx, mmid_device->name,
|
||||
ret);
|
||||
goto err;
|
||||
} else {
|
||||
pr_debug("gipc ep found for %d\n",
|
||||
ghs_vmm_plugin_info.curr);
|
||||
pr_debug("gipc ep found for %d %s\n",
|
||||
dt_name_idx, mmid_device->name);
|
||||
}
|
||||
} else {
|
||||
pr_err("of_parse_phandle failed id: %d\n",
|
||||
ghs_vmm_plugin_info.curr);
|
||||
pr_err("of_parse_phandle failed id %d %s\n",
|
||||
dt_name_idx, mmid_device->name);
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
pr_err("of_find_compatible_node failed id: %d\n",
|
||||
ghs_vmm_plugin_info.curr);
|
||||
pr_err("of_find_compatible_node failed id %d %s\n",
|
||||
dt_name_idx, mmid_device->name);
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
@ -149,6 +220,7 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
|
|||
pchan->hyp_data = (void *)dev;
|
||||
pchan->is_be = is_be;
|
||||
strlcpy(dev->name, name, sizeof(dev->name));
|
||||
strlcpy(pchan->name, name, sizeof(pchan->name));
|
||||
*ppchan = pchan;
|
||||
dev->read_data = kmalloc(GIPC_RECV_BUFF_SIZE_BYTES, GFP_KERNEL);
|
||||
if (!dev->read_data) {
|
||||
|
|
|
@ -124,8 +124,11 @@ void habmem_remove_export(struct export_desc *exp)
|
|||
struct uhab_context *ctx;
|
||||
|
||||
if (!exp || !exp->ctx || !exp->pchan) {
|
||||
pr_err("failed to find valid info in exp %pK ctx %pK pchan %pK\n",
|
||||
if (exp)
|
||||
pr_err("invalid info in exp %pK ctx %pK pchan %pK\n",
|
||||
exp, exp->ctx, exp->pchan);
|
||||
else
|
||||
pr_err("invalid exp\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,8 +76,9 @@ hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
|
|||
ret = 0;
|
||||
*rsize = message->sizebytes;
|
||||
} else {
|
||||
pr_err("rcv buffer too small %d < %zd\n",
|
||||
*rsize, message->sizebytes);
|
||||
pr_err("vcid %x rcv buf too small %d < %zd\n",
|
||||
vchan->id, *rsize,
|
||||
message->sizebytes);
|
||||
*rsize = message->sizebytes;
|
||||
message = NULL;
|
||||
ret = -EOVERFLOW; /* come back again */
|
||||
|
@ -281,7 +282,13 @@ int hab_msg_recv(struct physical_channel *pchan,
|
|||
break;
|
||||
}
|
||||
|
||||
exp_desc->domid_local = pchan->dom_id;
|
||||
if (pchan->vmid_local != exp_desc->domid_remote ||
|
||||
pchan->vmid_remote != exp_desc->domid_local)
|
||||
pr_err("corrupted vmid %d != %d %d != %d\n",
|
||||
pchan->vmid_local, exp_desc->domid_remote,
|
||||
pchan->vmid_remote, exp_desc->domid_local);
|
||||
exp_desc->domid_remote = pchan->vmid_remote;
|
||||
exp_desc->domid_local = pchan->vmid_local;
|
||||
exp_desc->pchan = pchan;
|
||||
|
||||
hab_export_enqueue(vchan, exp_desc);
|
||||
|
|
|
@ -152,10 +152,13 @@ int hab_open_listen(struct uhab_context *ctx,
|
|||
ret = wait_event_interruptible_timeout(dev->openq,
|
||||
hab_open_request_find(ctx, dev, listen, recv_request),
|
||||
ms_timeout);
|
||||
if (!ret || (-ERESTARTSYS == ret)) {
|
||||
if (!ret) {
|
||||
pr_debug("%s timeout in open listen\n", dev->name);
|
||||
ret = -EAGAIN; /* condition not met */
|
||||
} else if (-ERESTARTSYS == ret) {
|
||||
pr_warn("something failed in open listen ret %d\n",
|
||||
ret);
|
||||
ret = -EAGAIN; /* condition not met */
|
||||
ret = -EINTR; /* condition not met */
|
||||
} else if (ret > 0)
|
||||
ret = 0; /* condition met */
|
||||
} else { /* fe case */
|
||||
|
|
|
@ -87,7 +87,6 @@ hab_vchan_free(struct kref *ref)
|
|||
|
||||
/* the release vchan from ctx was done earlier in vchan close() */
|
||||
hab_ctx_put(ctx); /* now ctx is not needed from this vchan's view */
|
||||
vchan->ctx = NULL;
|
||||
|
||||
/* release vchan from pchan. no more msg for this vchan */
|
||||
write_lock_bh(&pchan->vchans_lock);
|
||||
|
@ -173,7 +172,10 @@ void hab_vchan_stop(struct virtual_channel *vchan)
|
|||
if (vchan) {
|
||||
vchan->otherend_closed = 1;
|
||||
wake_up(&vchan->rx_queue);
|
||||
wake_up_interruptible(&vchan->ctx->exp_wq);
|
||||
if (vchan->ctx)
|
||||
wake_up_interruptible(&vchan->ctx->exp_wq);
|
||||
else
|
||||
pr_err("NULL ctx for vchan %x\n", vchan->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,6 +202,18 @@ static int hab_vchans_per_pchan_empty(struct physical_channel *pchan)
|
|||
|
||||
read_lock(&pchan->vchans_lock);
|
||||
empty = list_empty(&pchan->vchannels);
|
||||
if (!empty) {
|
||||
struct virtual_channel *vchan;
|
||||
|
||||
list_for_each_entry(vchan, &pchan->vchannels, pnode) {
|
||||
pr_err("vchan %pK id %x remote id %x session %d ref %d closed %d remote close %d\n",
|
||||
vchan, vchan->id, vchan->otherend_id,
|
||||
vchan->session_id,
|
||||
get_refcnt(vchan->refcount), vchan->closed,
|
||||
vchan->otherend_closed);
|
||||
}
|
||||
|
||||
}
|
||||
read_unlock(&pchan->vchans_lock);
|
||||
|
||||
return empty;
|
||||
|
@ -220,6 +234,8 @@ static int hab_vchans_empty(int vmid)
|
|||
if (!hab_vchans_per_pchan_empty(pchan)) {
|
||||
empty = 0;
|
||||
spin_unlock_bh(&hab_dev->pchan_lock);
|
||||
pr_info("vmid %d %s's vchans are not closed\n",
|
||||
vmid, pchan->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +255,7 @@ void hab_vchans_empty_wait(int vmid)
|
|||
pr_info("waiting for GVM%d's sockets closure\n", vmid);
|
||||
|
||||
while (!hab_vchans_empty(vmid))
|
||||
schedule();
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
pr_info("all of GVM%d's sockets are closed\n", vmid);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
#define MM_VID_START 500
|
||||
#define MM_VID 501
|
||||
#define MM_VID_END 502
|
||||
#define MM_VID_2 502
|
||||
#define MM_VID_END 503
|
||||
|
||||
#define MM_MISC_START 600
|
||||
#define MM_MISC 601
|
||||
|
@ -37,10 +38,7 @@
|
|||
|
||||
#define MM_QCPE_START 700
|
||||
#define MM_QCPE_VM1 701
|
||||
#define MM_QCPE_VM2 702
|
||||
#define MM_QCPE_VM3 703
|
||||
#define MM_QCPE_VM4 704
|
||||
#define MM_QCPE_END 705
|
||||
#define MM_QCPE_END 702
|
||||
|
||||
#define MM_CLK_START 800
|
||||
#define MM_CLK_VM1 801
|
||||
|
|
Loading…
Add table
Reference in a new issue