summaryrefslogtreecommitdiff
path: root/gxp-vd.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxp-vd.c')
-rw-r--r--gxp-vd.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/gxp-vd.c b/gxp-vd.c
index fcb99ea..bc5a6e3 100644
--- a/gxp-vd.c
+++ b/gxp-vd.c
@@ -21,33 +21,43 @@ int gxp_vd_init(struct gxp_dev *gxp)
uint core;
int ret;
- mutex_init(&gxp->vd_lock);
- mutex_lock(&gxp->vd_lock);
+ init_rwsem(&gxp->vd_semaphore);
- /* Mark all cores as free */
+ /* All cores start as free */
for (core = 0; core < GXP_NUM_CORES; core++)
gxp->core_to_client[core] = NULL;
ret = gxp_fw_init(gxp);
- mutex_unlock(&gxp->vd_lock);
+
return ret;
}
void gxp_vd_destroy(struct gxp_dev *gxp)
{
- mutex_lock(&gxp->vd_lock);
+ down_write(&gxp->vd_semaphore);
gxp_fw_destroy(gxp);
- mutex_unlock(&gxp->vd_lock);
+ up_write(&gxp->vd_semaphore);
}
-/* Caller must hold gxp->vd_lock */
+/* Caller must hold gxp->vd_semaphore for writing */
static void gxp_vd_release(struct gxp_client *client)
{
uint core;
struct gxp_dev *gxp = client->gxp;
+ /*
+ * Put all cores in the VD into reset so they can not wake each other up
+ */
+ for (core = 0; core < GXP_NUM_CORES; core++) {
+ if (gxp->core_to_client[core] == client) {
+ gxp_write_32_core(
+ gxp, core, GXP_REG_ETM_PWRCTL,
+ 1 << GXP_REG_ETM_PWRCTL_CORE_RESET_SHIFT);
+ }
+ }
+
for (core = 0; core < GXP_NUM_CORES; core++) {
if (gxp->core_to_client[core] == client) {
gxp->core_to_client[core] = NULL;
@@ -60,7 +70,7 @@ static void gxp_vd_release(struct gxp_client *client)
}
}
-/* Caller must hold gxp->vd_lock */
+/* Caller must hold gxp->vd_semaphore for writing */
int gxp_vd_allocate(struct gxp_client *client, u16 requested_cores)
{
struct gxp_dev *gxp = client->gxp;
@@ -133,10 +143,10 @@ int gxp_vd_virt_core_to_phys_core(struct gxp_client *client, u16 virt_core)
uint phys_core;
uint virt_core_index = 0;
- mutex_lock(&gxp->vd_lock);
+ down_read(&gxp->vd_semaphore);
if (!client->vd_allocated) {
- mutex_unlock(&gxp->vd_lock);
+ up_read(&gxp->vd_semaphore);
dev_dbg(gxp->dev, "Client has not allocated a virtual device\n");
return -EINVAL;
}
@@ -145,7 +155,7 @@ int gxp_vd_virt_core_to_phys_core(struct gxp_client *client, u16 virt_core)
if (gxp->core_to_client[phys_core] == client) {
if (virt_core_index == virt_core) {
/* Found virtual core */
- mutex_unlock(&gxp->vd_lock);
+ up_read(&gxp->vd_semaphore);
return phys_core;
}
@@ -153,7 +163,7 @@ int gxp_vd_virt_core_to_phys_core(struct gxp_client *client, u16 virt_core)
}
}
- mutex_unlock(&gxp->vd_lock);
+ up_read(&gxp->vd_semaphore);
dev_dbg(gxp->dev, "No mapping for virtual core %u\n", virt_core);
return -EINVAL;
}
@@ -207,18 +217,18 @@ void gxp_client_destroy(struct gxp_client *client)
{
struct gxp_dev *gxp = client->gxp;
- mutex_lock(&gxp->vd_lock);
+ down_write(&gxp->vd_semaphore);
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_ANDROID) && !IS_ENABLED(CONFIG_GXP_GEM5)
/*
* Unmap TPU buffers, if the mapping is already removed, this
* is a no-op.
*/
gxp_dma_unmap_tpu_buffer(gxp, client->mbx_desc);
-#endif // CONFIG_ANDROID
+#endif // CONFIG_ANDROID && !CONFIG_GXP_GEM5
gxp_vd_release(client);
- mutex_unlock(&gxp->vd_lock);
+ up_write(&gxp->vd_semaphore);
kfree(client);
}