summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-10-11 07:01:22 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2018-10-11 07:01:22 -0700
commit51abefff9fb42c8834acb643d6aa70d855e0cf43 (patch)
treeb84c2d0d3887a88d74c6dc5e90b428baae6492cf
parentd5c9ceb9a010310e03be83cdea1c707be2d41ff4 (diff)
parent23beddbfdf17cfa08dd7f3626895f0ba70dbfb16 (diff)
Merge "soc: hab: recycle mmid from qcpe to video"
-rw-r--r--drivers/soc/qcom/hab/hab.c48
-rw-r--r--drivers/soc/qcom/hab/hab.h9
-rw-r--r--drivers/soc/qcom/hab/hab_ghs.c96
-rw-r--r--drivers/soc/qcom/hab/hab_mimex.c5
-rw-r--r--drivers/soc/qcom/hab/hab_msg.c13
-rw-r--r--drivers/soc/qcom/hab/hab_open.c7
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c22
-rw-r--r--include/uapi/linux/habmmid.h8
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