summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/soc/qcom/hab/hab.h6
-rw-r--r--drivers/soc/qcom/hab/hab_pchan.c2
-rw-r--r--drivers/soc/qcom/hab/hab_qvm.c27
-rw-r--r--drivers/soc/qcom/hab/hab_qvm.h1
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c24
5 files changed, 60 insertions, 0 deletions
diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h
index 7f7c1e1f7370..c3c42cd0d44e 100644
--- a/drivers/soc/qcom/hab/hab.h
+++ b/drivers/soc/qcom/hab/hab.h
@@ -141,6 +141,10 @@ struct physical_channel {
int closed;
spinlock_t rxbuf_lock;
+
+ /* vchans over this pchan */
+ struct list_head vchannels;
+ rwlock_t vchans_lock;
};
struct hab_open_send_data {
@@ -246,6 +250,7 @@ struct virtual_channel {
struct physical_channel *pchan;
struct uhab_context *ctx;
struct list_head node;
+ struct list_head pnode;
struct list_head rx_list;
wait_queue_head_t rx_queue;
spinlock_t rx_lock;
@@ -289,6 +294,7 @@ struct hab_message *hab_vchan_recv(struct uhab_context *ctx,
int vcid,
unsigned int flags);
void hab_vchan_stop(struct virtual_channel *vchan);
+void hab_vchans_stop(struct physical_channel *pchan);
void hab_vchan_stop_notify(struct virtual_channel *vchan);
int hab_mem_export(struct uhab_context *ctx,
diff --git a/drivers/soc/qcom/hab/hab_pchan.c b/drivers/soc/qcom/hab/hab_pchan.c
index 1ad727f7d90f..199b7e2ccccb 100644
--- a/drivers/soc/qcom/hab/hab_pchan.c
+++ b/drivers/soc/qcom/hab/hab_pchan.c
@@ -31,6 +31,8 @@ hab_pchan_alloc(struct hab_device *habdev, int otherend_id)
pchan->closed = 1;
pchan->hyp_data = NULL;
+ INIT_LIST_HEAD(&pchan->vchannels);
+ rwlock_init(&pchan->vchans_lock);
spin_lock_init(&pchan->rxbuf_lock);
mutex_lock(&habdev->pchan_lock);
diff --git a/drivers/soc/qcom/hab/hab_qvm.c b/drivers/soc/qcom/hab/hab_qvm.c
index a37590f23c61..bfb968196997 100644
--- a/drivers/soc/qcom/hab/hab_qvm.c
+++ b/drivers/soc/qcom/hab/hab_qvm.c
@@ -104,6 +104,15 @@ static int create_dispatcher(struct physical_channel *pchan, int id)
return ret;
}
+void hab_pipe_reset(struct physical_channel *pchan)
+{
+ struct hab_pipe_endpoint *pipe_ep;
+ struct qvm_channel *dev = (struct qvm_channel *)pchan->hyp_data;
+
+ pipe_ep = hab_pipe_init(dev->pipe, PIPE_SHMEM_SIZE,
+ pchan->is_be ? 0 : 1);
+}
+
static struct physical_channel *habhyp_commdev_alloc(int id)
{
struct qvm_channel *dev;
@@ -220,6 +229,23 @@ static int hab_shmem_remove(struct platform_device *pdev)
return 0;
}
+static void hab_shmem_shutdown(struct platform_device *pdev)
+{
+ int i;
+ struct qvm_channel *dev;
+ struct physical_channel *pchan;
+ struct hab_device hab_dev;
+
+ for (i = 0; i < hab_driver.ndevices; i++) {
+ hab_dev = hab_driver.devp[i];
+ pr_debug("detaching %s\n", hab_dev.name);
+ list_for_each_entry(pchan, &hab_dev.pchannels, node) {
+ dev = (struct qvm_channel *)pchan->hyp_data;
+ dev->guest_ctrl->detach = 0;
+ }
+ }
+}
+
static const struct of_device_id hab_shmem_match_table[] = {
{.compatible = "qvm,guest_shm"},
{},
@@ -228,6 +254,7 @@ static const struct of_device_id hab_shmem_match_table[] = {
static struct platform_driver hab_shmem_driver = {
.probe = hab_shmem_probe,
.remove = hab_shmem_remove,
+ .shutdown = hab_shmem_shutdown,
.driver = {
.name = "hab_shmem",
.of_match_table = of_match_ptr(hab_shmem_match_table),
diff --git a/drivers/soc/qcom/hab/hab_qvm.h b/drivers/soc/qcom/hab/hab_qvm.h
index e94b82f87942..1e7b48f23478 100644
--- a/drivers/soc/qcom/hab/hab_qvm.h
+++ b/drivers/soc/qcom/hab/hab_qvm.h
@@ -43,5 +43,6 @@ struct qvm_channel {
#define PIPE_SHMEM_SIZE (128 * 1024)
void *qnx_hyp_rx_dispatch(void *data);
+void hab_pipe_reset(struct physical_channel *pchan);
#endif /* __HAB_QNX_H */
diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c
index 75a3fad68ab5..94abe628e967 100644
--- a/drivers/soc/qcom/hab/hab_vchan.c
+++ b/drivers/soc/qcom/hab/hab_vchan.c
@@ -40,6 +40,9 @@ hab_vchan_alloc(struct uhab_context *ctx, struct physical_channel *pchan)
hab_pchan_get(pchan);
vchan->pchan = pchan;
+ write_lock(&pchan->vchans_lock);
+ list_add_tail(&vchan->pnode, &pchan->vchannels);
+ write_unlock(&pchan->vchans_lock);
vchan->id = ((id << HAB_VCID_ID_SHIFT) & HAB_VCID_ID_MASK) |
((pchan->habdev->id << HAB_VCID_MMID_SHIFT) &
HAB_VCID_MMID_MASK) |
@@ -69,6 +72,7 @@ hab_vchan_free(struct kref *ref)
struct export_desc *exp;
struct physical_channel *pchan = vchan->pchan;
struct uhab_context *ctx = vchan->ctx;
+ struct virtual_channel *vc, *vc_tmp;
list_for_each_entry_safe(message, msg_tmp, &vchan->rx_list, node) {
list_del(&message->node);
@@ -117,6 +121,15 @@ hab_vchan_free(struct kref *ref)
idr_remove(&pchan->vchan_idr, HAB_VCID_GET_ID(vchan->id));
spin_unlock_bh(&pchan->vid_lock);
+ write_lock(&pchan->vchans_lock);
+ list_for_each_entry_safe(vc, vc_tmp, &pchan->vchannels, pnode) {
+ if (vchan == vc) {
+ list_del(&vc->pnode);
+ break;
+ }
+ }
+ write_unlock(&pchan->vchans_lock);
+
hab_pchan_put(pchan);
hab_ctx_put(ctx);
@@ -146,6 +159,17 @@ void hab_vchan_stop(struct virtual_channel *vchan)
}
}
+void hab_vchans_stop(struct physical_channel *pchan)
+{
+ struct virtual_channel *vchan, *tmp;
+
+ read_lock(&pchan->vchans_lock);
+ list_for_each_entry_safe(vchan, tmp, &pchan->vchannels, pnode) {
+ hab_vchan_stop(vchan);
+ }
+ read_unlock(&pchan->vchans_lock);
+}
+
void hab_vchan_stop_notify(struct virtual_channel *vchan)
{
hab_send_close_msg(vchan);