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:
Shiju Mathew 2018-10-03 20:18:58 -04:00
parent 2592658a93
commit 23beddbfdf
8 changed files with 155 additions and 53 deletions

View file

@ -21,7 +21,7 @@
.openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\ .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 * 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_DISP5_NAME, MM_DISP_5, 10),
HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 11), HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 11),
HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 12), HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 12),
HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 13), HAB_DEVICE_CNSTR(DEVICE_VID2_NAME, MM_VID_2, 13),
HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 14), HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 14),
HAB_DEVICE_CNSTR(DEVICE_QCPE2_NAME, MM_QCPE_VM2, 15), HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 15),
HAB_DEVICE_CNSTR(DEVICE_QCPE3_NAME, MM_QCPE_VM3, 16), HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 16),
HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 17), HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 17),
HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 18), HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 18),
HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 19), HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 19),
HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 20),
HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 21),
}; };
struct hab_driver hab_driver = { 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 */ /* notify remote side on vchan closing */
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) { list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
list_del(&vchan->node); /* vchan is not in this ctx anymore */ 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); write_unlock(&ctx->ctx_lock);
if (!vchan->closed) { hab_vchan_put(vchan); /* there is a lock inside */
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 */
}
write_lock(&ctx->ctx_lock); write_lock(&ctx->ctx_lock);
} }
@ -1324,7 +1332,6 @@ static int __init hab_init(void)
dev_t dev; dev_t dev;
place_marker("M - HAB INIT Start"); place_marker("M - HAB INIT Start");
result = alloc_chrdev_region(&hab_driver.major, 0, 1, "hab"); result = alloc_chrdev_region(&hab_driver.major, 0, 1, "hab");
if (result < 0) { if (result < 0) {
@ -1379,11 +1386,8 @@ static int __init hab_init(void)
} else } else
set_dma_ops(hab_driver.dev, &hab_dma_ops); set_dma_ops(hab_driver.dev, &hab_dma_ops);
} }
hab_stat_init(&hab_driver); hab_stat_init(&hab_driver);
place_marker("M - HAB INIT End"); place_marker("M - HAB INIT End");
return result; return result;
err: err:

View file

@ -45,6 +45,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/delay.h>
#include <soc/qcom/boot_stats.h> #include <soc/qcom/boot_stats.h>
enum hab_payload_type { enum hab_payload_type {
@ -81,11 +82,9 @@ enum hab_payload_type {
#define DEVICE_DISP5_NAME "hab_disp5" #define DEVICE_DISP5_NAME "hab_disp5"
#define DEVICE_GFX_NAME "hab_ogles" #define DEVICE_GFX_NAME "hab_ogles"
#define DEVICE_VID_NAME "hab_vid" #define DEVICE_VID_NAME "hab_vid"
#define DEVICE_VID2_NAME "hab_vid2"
#define DEVICE_MISC_NAME "hab_misc" #define DEVICE_MISC_NAME "hab_misc"
#define DEVICE_QCPE1_NAME "hab_qcpe_vm1" #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_CLK1_NAME "hab_clock_vm1"
#define DEVICE_CLK2_NAME "hab_clock_vm2" #define DEVICE_CLK2_NAME "hab_clock_vm2"
#define DEVICE_FDE1_NAME "hab_fde1" #define DEVICE_FDE1_NAME "hab_fde1"
@ -346,6 +345,8 @@ struct hab_driver {
}; };
struct virtual_channel { 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 * refcount is used to track the references from hab core to the virtual
* channel such as references from physical channels, * channel such as references from physical channels,
@ -354,8 +355,6 @@ struct virtual_channel {
struct kref refcount; struct kref refcount;
struct physical_channel *pchan; struct physical_channel *pchan;
struct uhab_context *ctx; struct uhab_context *ctx;
struct list_head node; /* for ctx */
struct list_head pnode; /* for pchan */
struct list_head rx_list; struct list_head rx_list;
wait_queue_head_t rx_queue; wait_queue_head_t rx_queue;
spinlock_t rx_lock; spinlock_t rx_lock;

View file

@ -14,6 +14,7 @@
#include "hab.h" #include "hab.h"
#include "hab_ghs.h" #include "hab_ghs.h"
#define GIPC_VM_SET_CNT 22
static const char * const dt_gipc_path_name[] = { static const char * const dt_gipc_path_name[] = {
"testgipc1", "testgipc1",
"testgipc2", "testgipc2",
@ -39,12 +40,41 @@ static const char * const dt_gipc_path_name[] = {
"testgipc22", "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 { static struct ghs_vmm_plugin_info_s {
const char * const *dt_name; const char * const *dt_name;
int *mmid_dt_mapping;
int curr; int curr;
int probe_cnt; int probe_cnt;
} ghs_vmm_plugin_info = { } ghs_vmm_plugin_info = {
dt_gipc_path_name, dt_gipc_path_name,
mmid_order,
0, 0,
ARRAY_SIZE(dt_gipc_path_name), ARRAY_SIZE(dt_gipc_path_name),
}; };
@ -59,6 +89,33 @@ static void ghs_irq_handler(void *cookie)
tasklet_schedule(&dev->task); 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) */ /* static struct physical_channel *habhyp_commdev_alloc(int id) */
int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote, int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
struct hab_device *mmid_device) 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 *pchan = NULL;
struct physical_channel **ppchan = (struct physical_channel **)commdev; struct physical_channel **ppchan = (struct physical_channel **)commdev;
int ret = 0; int ret = 0;
int dt_name_idx = 0;
if (ghs_vmm_plugin_info.curr > ghs_vmm_plugin_info.probe_cnt) { if (ghs_vmm_plugin_info.curr > ghs_vmm_plugin_info.probe_cnt) {
pr_err("too many commdev alloc %d, supported is %d\n", 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"); gvh_dn = of_find_node_by_path("/aliases");
if (gvh_dn) { if (gvh_dn) {
const char *ep_path = NULL; 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, ret = of_property_read_string(gvh_dn,
ghs_vmm_plugin_info.dt_name[ghs_vmm_plugin_info.curr], ghs_vmm_plugin_info.dt_name[dt_name_idx],
&ep_path); &ep_path);
if (ret) if (ret)
pr_err("failed to read endpoint string ret %d\n", pr_err("failed to read endpoint str ret %d\n",
ret); ret);
of_node_put(gvh_dn); 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); of_node_put(ep_dn);
if (IS_ERR(dev->endpoint)) { if (IS_ERR(dev->endpoint)) {
ret = PTR_ERR(dev->endpoint); ret = PTR_ERR(dev->endpoint);
pr_err("KGIPC alloc failed id: %d, ret: %d\n", pr_err("alloc failed %d %s ret %d\n",
ghs_vmm_plugin_info.curr, ret); dt_name_idx, mmid_device->name,
ret);
goto err; goto err;
} else { } else {
pr_debug("gipc ep found for %d\n", pr_debug("gipc ep found for %d %s\n",
ghs_vmm_plugin_info.curr); dt_name_idx, mmid_device->name);
} }
} else { } else {
pr_err("of_parse_phandle failed id: %d\n", pr_err("of_parse_phandle failed id %d %s\n",
ghs_vmm_plugin_info.curr); dt_name_idx, mmid_device->name);
ret = -ENOENT; ret = -ENOENT;
goto err; goto err;
} }
} else { } else {
pr_err("of_find_compatible_node failed id: %d\n", pr_err("of_find_compatible_node failed id %d %s\n",
ghs_vmm_plugin_info.curr); dt_name_idx, mmid_device->name);
ret = -ENOENT; ret = -ENOENT;
goto err; 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->hyp_data = (void *)dev;
pchan->is_be = is_be; pchan->is_be = is_be;
strlcpy(dev->name, name, sizeof(dev->name)); strlcpy(dev->name, name, sizeof(dev->name));
strlcpy(pchan->name, name, sizeof(pchan->name));
*ppchan = pchan; *ppchan = pchan;
dev->read_data = kmalloc(GIPC_RECV_BUFF_SIZE_BYTES, GFP_KERNEL); dev->read_data = kmalloc(GIPC_RECV_BUFF_SIZE_BYTES, GFP_KERNEL);
if (!dev->read_data) { if (!dev->read_data) {

View file

@ -124,8 +124,11 @@ void habmem_remove_export(struct export_desc *exp)
struct uhab_context *ctx; struct uhab_context *ctx;
if (!exp || !exp->ctx || !exp->pchan) { 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); exp, exp->ctx, exp->pchan);
else
pr_err("invalid exp\n");
return; return;
} }

View file

@ -76,8 +76,9 @@ hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
ret = 0; ret = 0;
*rsize = message->sizebytes; *rsize = message->sizebytes;
} else { } else {
pr_err("rcv buffer too small %d < %zd\n", pr_err("vcid %x rcv buf too small %d < %zd\n",
*rsize, message->sizebytes); vchan->id, *rsize,
message->sizebytes);
*rsize = message->sizebytes; *rsize = message->sizebytes;
message = NULL; message = NULL;
ret = -EOVERFLOW; /* come back again */ ret = -EOVERFLOW; /* come back again */
@ -281,7 +282,13 @@ int hab_msg_recv(struct physical_channel *pchan,
break; 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; exp_desc->pchan = pchan;
hab_export_enqueue(vchan, exp_desc); hab_export_enqueue(vchan, exp_desc);

View file

@ -152,10 +152,13 @@ int hab_open_listen(struct uhab_context *ctx,
ret = wait_event_interruptible_timeout(dev->openq, ret = wait_event_interruptible_timeout(dev->openq,
hab_open_request_find(ctx, dev, listen, recv_request), hab_open_request_find(ctx, dev, listen, recv_request),
ms_timeout); 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", pr_warn("something failed in open listen ret %d\n",
ret); ret);
ret = -EAGAIN; /* condition not met */ ret = -EINTR; /* condition not met */
} else if (ret > 0) } else if (ret > 0)
ret = 0; /* condition met */ ret = 0; /* condition met */
} else { /* fe case */ } else { /* fe case */

View file

@ -87,7 +87,6 @@ hab_vchan_free(struct kref *ref)
/* the release vchan from ctx was done earlier in vchan close() */ /* 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 */ 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 */ /* release vchan from pchan. no more msg for this vchan */
write_lock_bh(&pchan->vchans_lock); write_lock_bh(&pchan->vchans_lock);
@ -173,7 +172,10 @@ void hab_vchan_stop(struct virtual_channel *vchan)
if (vchan) { if (vchan) {
vchan->otherend_closed = 1; vchan->otherend_closed = 1;
wake_up(&vchan->rx_queue); 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); read_lock(&pchan->vchans_lock);
empty = list_empty(&pchan->vchannels); 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); read_unlock(&pchan->vchans_lock);
return empty; return empty;
@ -220,6 +234,8 @@ static int hab_vchans_empty(int vmid)
if (!hab_vchans_per_pchan_empty(pchan)) { if (!hab_vchans_per_pchan_empty(pchan)) {
empty = 0; empty = 0;
spin_unlock_bh(&hab_dev->pchan_lock); spin_unlock_bh(&hab_dev->pchan_lock);
pr_info("vmid %d %s's vchans are not closed\n",
vmid, pchan->name);
break; break;
} }
} }
@ -239,7 +255,7 @@ void hab_vchans_empty_wait(int vmid)
pr_info("waiting for GVM%d's sockets closure\n", vmid); pr_info("waiting for GVM%d's sockets closure\n", vmid);
while (!hab_vchans_empty(vmid)) while (!hab_vchans_empty(vmid))
schedule(); usleep_range(10000, 12000);
pr_info("all of GVM%d's sockets are closed\n", vmid); pr_info("all of GVM%d's sockets are closed\n", vmid);
} }

View file

@ -29,7 +29,8 @@
#define MM_VID_START 500 #define MM_VID_START 500
#define MM_VID 501 #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_START 600
#define MM_MISC 601 #define MM_MISC 601
@ -37,10 +38,7 @@
#define MM_QCPE_START 700 #define MM_QCPE_START 700
#define MM_QCPE_VM1 701 #define MM_QCPE_VM1 701
#define MM_QCPE_VM2 702 #define MM_QCPE_END 702
#define MM_QCPE_VM3 703
#define MM_QCPE_VM4 704
#define MM_QCPE_END 705
#define MM_CLK_START 800 #define MM_CLK_START 800
#define MM_CLK_VM1 801 #define MM_CLK_VM1 801