diff options
| -rw-r--r-- | drivers/soc/qcom/hab/hab.h | 6 | ||||
| -rw-r--r-- | drivers/soc/qcom/hab/hab_pchan.c | 2 | ||||
| -rw-r--r-- | drivers/soc/qcom/hab/hab_qvm.c | 27 | ||||
| -rw-r--r-- | drivers/soc/qcom/hab/hab_qvm.h | 1 | ||||
| -rw-r--r-- | drivers/soc/qcom/hab/hab_vchan.c | 24 |
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); |
