diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2018-10-11 07:01:22 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-10-11 07:01:22 -0700 |
commit | 51abefff9fb42c8834acb643d6aa70d855e0cf43 (patch) | |
tree | b84c2d0d3887a88d74c6dc5e90b428baae6492cf | |
parent | d5c9ceb9a010310e03be83cdea1c707be2d41ff4 (diff) | |
parent | 23beddbfdf17cfa08dd7f3626895f0ba70dbfb16 (diff) |
Merge "soc: hab: recycle mmid from qcpe to video"
-rw-r--r-- | drivers/soc/qcom/hab/hab.c | 48 | ||||
-rw-r--r-- | drivers/soc/qcom/hab/hab.h | 9 | ||||
-rw-r--r-- | drivers/soc/qcom/hab/hab_ghs.c | 96 | ||||
-rw-r--r-- | drivers/soc/qcom/hab/hab_mimex.c | 5 | ||||
-rw-r--r-- | drivers/soc/qcom/hab/hab_msg.c | 13 | ||||
-rw-r--r-- | drivers/soc/qcom/hab/hab_open.c | 7 | ||||
-rw-r--r-- | drivers/soc/qcom/hab/hab_vchan.c | 22 | ||||
-rw-r--r-- | include/uapi/linux/habmmid.h | 8 |
8 files changed, 155 insertions, 53 deletions
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c index 5b84a57423b9..ebe7dfc4a5b6 100644 --- a/drivers/soc/qcom/hab/hab.c +++ b/drivers/soc/qcom/hab/hab.c @@ -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: diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h index c4e8eaa368e3..cbc049e89d63 100644 --- a/drivers/soc/qcom/hab/hab.h +++ b/drivers/soc/qcom/hab/hab.h @@ -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; diff --git a/drivers/soc/qcom/hab/hab_ghs.c b/drivers/soc/qcom/hab/hab_ghs.c index e743d9b00a66..a445aa1a6707 100644 --- a/drivers/soc/qcom/hab/hab_ghs.c +++ b/drivers/soc/qcom/hab/hab_ghs.c @@ -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) { diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c index d5786170f0f3..00c6c475fa92 100644 --- a/drivers/soc/qcom/hab/hab_mimex.c +++ b/drivers/soc/qcom/hab/hab_mimex.c @@ -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; } diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c index 3765623d3190..61e658954312 100644 --- a/drivers/soc/qcom/hab/hab_msg.c +++ b/drivers/soc/qcom/hab/hab_msg.c @@ -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); diff --git a/drivers/soc/qcom/hab/hab_open.c b/drivers/soc/qcom/hab/hab_open.c index f740a43c1973..f09a1df8aa57 100644 --- a/drivers/soc/qcom/hab/hab_open.c +++ b/drivers/soc/qcom/hab/hab_open.c @@ -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 */ diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c index d572e4c8a34b..8d818b8fafb1 100644 --- a/drivers/soc/qcom/hab/hab_vchan.c +++ b/drivers/soc/qcom/hab/hab_vchan.c @@ -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); } diff --git a/include/uapi/linux/habmmid.h b/include/uapi/linux/habmmid.h index 4f79506dd971..1845c72c9e60 100644 --- a/include/uapi/linux/habmmid.h +++ b/include/uapi/linux/habmmid.h @@ -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 |