summaryrefslogtreecommitdiff
path: root/gxp-client.c
diff options
context:
space:
mode:
authorAurora zuma automerger <aurora-zuma-automerger@google.com>2022-08-23 10:37:49 +0000
committerdavidchiang <davidchiang@google.com>2022-08-24 03:57:45 +0000
commitf55f6c16e3f978707b167468762be063b6d5f078 (patch)
treeae6ddded688902d5f586f4e43c59b1f97b210636 /gxp-client.c
parentabf988eedc285b626c0f207c3ba33c9c8c7236ad (diff)
downloadzuma-f55f6c16e3f978707b167468762be063b6d5f078.tar.gz
[Copybara Auto Merge] Merge branch 'zuma' into 'android13-gs-pixel-5.15'
gxp: fix various typos gxp: Protect telemetry status in vd alloc/release Bug: 242145264 gxp: Fail to allocate VD if initial mapping fails Bug: 242145264 (repeat) gxp: Use one gxp_mailbox_create_manager Bug: 242939166 gxp: Extract mailbox manager from gxp-mailbox.h Bug: 242939166 (repeat) gxp: Implement the mailbox manager operator setting function of UCI Bug: 242178774 gxp: Add init functions for the legacy mailbox and DCI Bug: 242178774 (repeat) gxp: Introduce `GXP_HAS_DCI` definition Bug: 242964051 gxp: Introduce `callisto_dev_parse_work_mode` function Bug: 242964051 (repeat) gxp: Expose callisto_work_mode_name Bug: 242964051 (repeat) gxp: fix error handling on probing gxp: callisto: Change CORE_PD_COUNT Bug: 236046046 gcip: Add linux/workqueue.h as header GCIP_HEADERS_REV_ID: 8acbda22d491fc500a17f5bdd70d776d132e7e72 gxp: not push wakelock UCI response into the queue Bug: 241782481 gxp: append internal headers after EXTRA_CFLAGS Bug: 242960640 gxp: remove GXP_POWER_STATE_OFF check in mbox cmd gxp: Implement Callisto wakelock UCI commands Bug: 241782481 (repeat) gxp: Add power states requests callback Bug: 241782481 (repeat) gxp: move UCI_RESOURCE_ID into gxp-uci.h Bug: 241782481 (repeat) gxp: Allocate resources on VD creation Bug: 241206240 gxp: handle VD allocation in gxp-client.c Bug: 241206240 (repeat) gxp: handle wakelock request in gxp-client.c Bug: 241206240 (repeat) gxp: gxp_mapping_create accepts domain Bug: 240415495 gxp: split out gxp_vd & gxp_fw module init/destroy Bug: 193180931 gxp: fixup DVFS requests Bug: 242785262 gxp: temporarily ignore KCI timeouts Bug: 215413402 gxp: Only (un)map telem if enabled on vd start/stop Bug: 241090227 gxp: release TPU file after VD stop Bug: 241085004 gxp: increase the ref to TPU FD on TPU buffer map Bug: 241085004 (repeat) GitOrigin-RevId: b82342a13c0a981c47afee8883f8df2426ccf67f Change-Id: Iec484770d372863d0ba260d8ec0ec0565a700898
Diffstat (limited to 'gxp-client.c')
-rw-r--r--gxp-client.c204
1 files changed, 190 insertions, 14 deletions
diff --git a/gxp-client.c b/gxp-client.c
index 8ea2b61..ab4bc8a 100644
--- a/gxp-client.c
+++ b/gxp-client.c
@@ -31,7 +31,6 @@ struct gxp_client *gxp_client_create(struct gxp_dev *gxp)
client->requested_power_state = AUR_OFF;
client->requested_memory_power_state = 0;
client->vd = NULL;
- client->tpu_mbx_allocated = false;
client->requested_low_clkmux = false;
return client;
}
@@ -41,26 +40,26 @@ void gxp_client_destroy(struct gxp_client *client)
struct gxp_dev *gxp = client->gxp;
int core;
- down_write(&gxp->vd_semaphore);
-
-#if (IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_ANDROID)) && !IS_ENABLED(CONFIG_GXP_GEM5)
- /*
- * Unmap TPU buffers, if the mapping is already removed, this
- * is a no-op.
- */
- if (client->vd)
- gxp_dma_unmap_tpu_buffer(gxp, client->vd->domain, client->mbx_desc);
-#endif
-
- if (client->vd && client->vd->state != GXP_VD_OFF)
+ if (client->vd && client->vd->state != GXP_VD_OFF) {
+ down_read(&gxp->vd_semaphore);
gxp_vd_stop(client->vd);
+ up_read(&gxp->vd_semaphore);
+ }
for (core = 0; core < GXP_NUM_CORES; core++) {
if (client->mb_eventfds[core])
gxp_eventfd_put(client->mb_eventfds[core]);
}
- up_write(&gxp->vd_semaphore);
+#if (IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_ANDROID)) && !IS_ENABLED(CONFIG_GXP_GEM5)
+ if (client->tpu_file) {
+ fput(client->tpu_file);
+ client->tpu_file = NULL;
+ if (client->vd)
+ gxp_dma_unmap_tpu_buffer(gxp, client->vd->domain,
+ client->mbx_desc);
+ }
+#endif
if (client->has_block_wakelock) {
gxp_wakelock_release(client->gxp);
@@ -74,8 +73,185 @@ void gxp_client_destroy(struct gxp_client *client)
if (client->vd) {
if (gxp->before_release_vd)
gxp->before_release_vd(gxp, client->vd);
+ down_write(&gxp->vd_semaphore);
gxp_vd_release(client->vd);
+ up_write(&gxp->vd_semaphore);
}
kfree(client);
}
+
+int gxp_client_allocate_virtual_device(struct gxp_client *client,
+ uint core_count)
+{
+ struct gxp_dev *gxp = client->gxp;
+ struct gxp_virtual_device *vd;
+ int ret;
+
+ lockdep_assert_held(&client->semaphore);
+ if (client->vd) {
+ dev_err(gxp->dev,
+ "Virtual device was already allocated for client\n");
+ return -EINVAL;
+ }
+
+ down_write(&gxp->vd_semaphore);
+ vd = gxp_vd_allocate(gxp, core_count);
+ if (IS_ERR(vd)) {
+ ret = PTR_ERR(vd);
+ dev_err(gxp->dev,
+ "Failed to allocate virtual device for client (%d)\n",
+ ret);
+ goto error;
+ }
+
+ if (gxp->after_allocate_vd) {
+ ret = gxp->after_allocate_vd(gxp, vd);
+ if (ret) {
+ gxp_vd_release(vd);
+ goto error;
+ }
+ }
+ up_write(&gxp->vd_semaphore);
+
+ if (client->has_block_wakelock)
+ gxp_vd_block_ready(client->vd);
+
+ client->vd = vd;
+ return 0;
+error:
+ up_write(&gxp->vd_semaphore);
+ return ret;
+}
+
+static int gxp_client_request_power_states(struct gxp_client *client,
+ uint power_state,
+ uint memory_power_state,
+ bool low_clkmux)
+{
+ struct gxp_dev *gxp = client->gxp;
+ int ret;
+
+ if (gxp->request_power_states) {
+ ret = gxp->request_power_states(client, power_state,
+ memory_power_state, low_clkmux);
+ if (ret != -EOPNOTSUPP)
+ return ret;
+ }
+ gxp_pm_update_requested_power_states(
+ gxp, client->requested_power_state,
+ client->requested_low_clkmux, power_state, low_clkmux,
+ client->requested_memory_power_state,
+ memory_power_state);
+ client->requested_power_state = power_state;
+ client->requested_low_clkmux = low_clkmux;
+ client->requested_memory_power_state = memory_power_state;
+ return 0;
+}
+
+int gxp_client_acquire_block_wakelock(struct gxp_client *client,
+ bool *acquired_wakelock, uint power_state,
+ uint memory_power_state, bool low_clkmux)
+{
+ struct gxp_dev *gxp = client->gxp;
+ int ret;
+
+ lockdep_assert_held(&client->semaphore);
+ if (!client->has_block_wakelock) {
+ ret = gxp_wakelock_acquire(gxp);
+ if (ret)
+ return ret;
+ *acquired_wakelock = true;
+ if (client->vd)
+ gxp_vd_block_ready(client->vd);
+ } else {
+ *acquired_wakelock = false;
+ }
+ client->has_block_wakelock = true;
+
+ /*
+ * Update client's TGID+PID in case the process that opened
+ * /dev/gxp is not the one that called this IOCTL.
+ */
+ client->tgid = current->tgid;
+ client->pid = current->pid;
+
+ ret = gxp_client_request_power_states(client, power_state,
+ memory_power_state, low_clkmux);
+
+ return ret;
+}
+
+void gxp_client_release_block_wakelock(struct gxp_client *client)
+{
+ struct gxp_dev *gxp = client->gxp;
+
+ lockdep_assert_held(&client->semaphore);
+ if (!client->has_block_wakelock)
+ return;
+
+ if (client->has_vd_wakelock)
+ gxp_client_release_vd_wakelock(client);
+
+ gxp_client_request_power_states(client, AUR_OFF, AUR_MEM_UNDEFINED,
+ false);
+ gxp_wakelock_release(gxp);
+ client->has_block_wakelock = false;
+}
+
+int gxp_client_acquire_vd_wakelock(struct gxp_client *client)
+{
+ struct gxp_dev *gxp = client->gxp;
+ int ret = 0;
+
+ lockdep_assert_held(&client->semaphore);
+ if (!client->has_block_wakelock) {
+ dev_err(gxp->dev,
+ "Must hold BLOCK wakelock to acquire VIRTUAL_DEVICE wakelock\n");
+ return -EINVAL;
+ }
+
+ if (client->vd->state == GXP_VD_UNAVAILABLE) {
+ dev_err(gxp->dev,
+ "Cannot acquire VIRTUAL_DEVICE wakelock on a broken virtual device\n");
+ return -ENODEV;
+ }
+
+ if (!client->has_vd_wakelock) {
+ down_write(&gxp->vd_semaphore);
+ if (client->vd->state == GXP_VD_READY || client->vd->state == GXP_VD_OFF)
+ ret = gxp_vd_run(client->vd);
+ else
+ ret = gxp_vd_resume(client->vd);
+ up_write(&gxp->vd_semaphore);
+ }
+
+ if (!ret)
+ client->has_vd_wakelock = true;
+
+ return ret;
+}
+
+void gxp_client_release_vd_wakelock(struct gxp_client *client)
+{
+ struct gxp_dev *gxp = client->gxp;
+
+ lockdep_assert_held(&client->semaphore);
+ if (!client->has_vd_wakelock)
+ return;
+
+ /*
+ * Currently VD state will not be GXP_VD_UNAVAILABLE if
+ * has_vd_wakelock is true. Add this check just in case
+ * GXP_VD_UNAVAILABLE will occur in more scenarios in the
+ * future.
+ */
+ if (client->vd->state == GXP_VD_UNAVAILABLE)
+ return;
+
+ down_write(&gxp->vd_semaphore);
+ gxp_vd_suspend(client->vd);
+ up_write(&gxp->vd_semaphore);
+
+ client->has_vd_wakelock = false;
+}