summaryrefslogtreecommitdiff
path: root/gxp-platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxp-platform.c')
-rw-r--r--gxp-platform.c167
1 files changed, 139 insertions, 28 deletions
diff --git a/gxp-platform.c b/gxp-platform.c
index df7ab49..96a3a76 100644
--- a/gxp-platform.c
+++ b/gxp-platform.c
@@ -5,7 +5,7 @@
* Copyright (C) 2021 Google LLC
*/
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
#include <linux/platform_data/sscoredump.h>
#endif
@@ -22,7 +22,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/uaccess.h>
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_ANDROID) && !IS_ENABLED(CONFIG_GXP_GEM5)
#include <soc/google/tpu-ext.h>
#endif
@@ -38,9 +38,11 @@
#include "gxp-mapping.h"
#include "gxp-pm.h"
#include "gxp-telemetry.h"
+#include "gxp-thermal.h"
#include "gxp-vd.h"
+#include "gxp-wakelock.h"
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
static struct sscd_platform_data gxp_sscd_pdata;
static void gxp_sscd_release(struct device *dev)
@@ -57,31 +59,51 @@ static struct platform_device gxp_sscd_dev = {
.release = gxp_sscd_release,
},
};
-#endif // CONFIG_ANDROID
+#endif // CONFIG_SUBSYSTEM_COREDUMP
static int gxp_open(struct inode *inode, struct file *file)
{
struct gxp_client *client;
struct gxp_dev *gxp = container_of(file->private_data, struct gxp_dev,
misc_dev);
+ int ret = 0;
client = gxp_client_create(gxp);
if (IS_ERR(client))
return PTR_ERR(client);
file->private_data = client;
- return 0;
+
+ ret = gxp_wakelock_acquire(gxp);
+ if (ret) {
+ gxp_client_destroy(client);
+ file->private_data = NULL;
+ }
+
+ return ret;
}
static int gxp_release(struct inode *inode, struct file *file)
{
struct gxp_client *client = file->private_data;
+ struct gxp_dev *gxp;
+
+ /*
+ * If open failed and no client was created then no clean-up is needed.
+ */
+ if (!client)
+ return 0;
+
+ gxp = client->gxp;
/*
* TODO (b/184572070): Unmap buffers and drop mailbox responses
* belonging to the client
*/
gxp_client_destroy(client);
+
+ gxp_wakelock_release(gxp);
+
return 0;
}
@@ -263,10 +285,12 @@ static int gxp_mailbox_command(struct gxp_client *client,
cmd.priority = 0; /* currently unused */
cmd.buffer_descriptor = buffer;
+ down_read(&gxp->vd_semaphore);
ret = gxp_mailbox_execute_cmd_async(
gxp->mailbox_mgr->mailboxes[phys_core], &cmd,
&gxp->mailbox_resp_queues[phys_core], &gxp->mailbox_resps_lock,
&gxp->mailbox_resp_waitqs[phys_core]);
+ up_read(&gxp->vd_semaphore);
if (ret) {
dev_err(gxp->dev, "Failed to enqueue mailbox command (ret=%d)\n",
ret);
@@ -411,15 +435,15 @@ static int gxp_allocate_vd(struct gxp_client *client,
return -EINVAL;
}
- mutex_lock(&gxp->vd_lock);
+ down_write(&gxp->vd_semaphore);
if (client->vd_allocated) {
- mutex_unlock(&gxp->vd_lock);
+ up_write(&gxp->vd_semaphore);
dev_err(gxp->dev, "Virtual device was already allocated for client\n");
return -EINVAL;
}
ret = gxp_vd_allocate(client, ibuf.core_count);
- mutex_unlock(&gxp->vd_lock);
+ up_write(&gxp->vd_semaphore);
return ret;
}
@@ -607,7 +631,7 @@ static int gxp_disable_telemetry(struct gxp_client *client, __u8 __user *argp)
static int gxp_map_tpu_mbx_queue(struct gxp_client *client,
struct gxp_tpu_mbx_queue_ioctl __user *argp)
{
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_ANDROID) && !IS_ENABLED(CONFIG_GXP_GEM5)
struct gxp_dev *gxp = client->gxp;
struct edgetpu_ext_mailbox_info *mbx_info;
struct gxp_tpu_mbx_queue_ioctl ibuf;
@@ -643,7 +667,7 @@ static int gxp_map_tpu_mbx_queue(struct gxp_client *client,
if (!mbx_info)
return -ENOMEM;
- mutex_lock(&gxp->vd_lock);
+ down_write(&gxp->vd_semaphore);
if (client->tpu_mbx_allocated) {
dev_err(gxp->dev, "%s: Mappings already exist for TPU mailboxes\n",
@@ -684,7 +708,7 @@ static int gxp_map_tpu_mbx_queue(struct gxp_client *client,
client->tpu_mbx_allocated = true;
error:
- mutex_unlock(&gxp->vd_lock);
+ up_write(&gxp->vd_semaphore);
kfree(mbx_info);
return ret;
@@ -696,7 +720,7 @@ error:
static int gxp_unmap_tpu_mbx_queue(struct gxp_client *client,
struct gxp_tpu_mbx_queue_ioctl __user *argp)
{
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_ANDROID) && !IS_ENABLED(CONFIG_GXP_GEM5)
struct gxp_dev *gxp = client->gxp;
struct gxp_tpu_mbx_queue_ioctl ibuf;
struct edgetpu_ext_client_info gxp_tpu_info;
@@ -705,7 +729,7 @@ static int gxp_unmap_tpu_mbx_queue(struct gxp_client *client,
if (copy_from_user(&ibuf, argp, sizeof(ibuf)))
return -EFAULT;
- mutex_lock(&gxp->vd_lock);
+ down_write(&gxp->vd_semaphore);
if (!client->tpu_mbx_allocated) {
dev_err(gxp->dev, "%s: No mappings exist for TPU mailboxes\n",
@@ -729,7 +753,7 @@ static int gxp_unmap_tpu_mbx_queue(struct gxp_client *client,
client->tpu_mbx_allocated = false;
out:
- mutex_unlock(&gxp->vd_lock);
+ up_write(&gxp->vd_semaphore);
return ret;
#else
@@ -737,6 +761,59 @@ out:
#endif
}
+static int gxp_register_telemetry_eventfd(
+ struct gxp_client *client,
+ struct gxp_register_telemetry_eventfd_ioctl __user *argp)
+{
+ struct gxp_dev *gxp = client->gxp;
+ struct gxp_register_telemetry_eventfd_ioctl ibuf;
+
+ if (copy_from_user(&ibuf, argp, sizeof(ibuf)))
+ return -EFAULT;
+
+ return gxp_telemetry_register_eventfd(gxp, ibuf.type, ibuf.eventfd);
+}
+
+static int gxp_unregister_telemetry_eventfd(
+ struct gxp_client *client,
+ struct gxp_register_telemetry_eventfd_ioctl __user *argp)
+{
+ struct gxp_dev *gxp = client->gxp;
+ struct gxp_register_telemetry_eventfd_ioctl ibuf;
+
+ if (copy_from_user(&ibuf, argp, sizeof(ibuf)))
+ return -EFAULT;
+
+ return gxp_telemetry_unregister_eventfd(gxp, ibuf.type);
+}
+
+static int gxp_read_global_counter(struct gxp_client *client,
+ __u64 __user *argp)
+{
+ struct gxp_dev *gxp = client->gxp;
+ u32 high_first, high_second, low;
+ u64 counter_val;
+
+ high_first = gxp_read_32(gxp, GXP_REG_GLOBAL_COUNTER_HIGH);
+ low = gxp_read_32(gxp, GXP_REG_GLOBAL_COUNTER_LOW);
+
+ /*
+ * Check if the lower 32 bits could have wrapped in-between reading
+ * the high and low bit registers by validating the higher 32 bits
+ * haven't changed.
+ */
+ high_second = gxp_read_32(gxp, GXP_REG_GLOBAL_COUNTER_HIGH);
+ if (high_first != high_second)
+ low = gxp_read_32(gxp, GXP_REG_GLOBAL_COUNTER_LOW);
+
+ counter_val = ((u64)high_second << 32) | low;
+
+ if (copy_to_user(argp, &counter_val, sizeof(counter_val)))
+ return -EFAULT;
+
+ return 0;
+}
+
static long gxp_ioctl(struct file *file, uint cmd, ulong arg)
{
struct gxp_client *client = file->private_data;
@@ -789,6 +866,15 @@ static long gxp_ioctl(struct file *file, uint cmd, ulong arg)
case GXP_UNMAP_TPU_MBX_QUEUE:
ret = gxp_unmap_tpu_mbx_queue(client, argp);
break;
+ case GXP_REGISTER_TELEMETRY_EVENTFD:
+ ret = gxp_register_telemetry_eventfd(client, argp);
+ break;
+ case GXP_UNREGISTER_TELEMETRY_EVENTFD:
+ ret = gxp_unregister_telemetry_eventfd(client, argp);
+ break;
+ case GXP_READ_GLOBAL_COUNTER:
+ ret = gxp_read_global_counter(client, argp);
+ break;
default:
ret = -ENOTTY; /* unknown command */
}
@@ -838,6 +924,8 @@ static int gxp_platform_probe(struct platform_device *pdev)
int i __maybe_unused;
bool tpu_found __maybe_unused;
+ dev_notice(dev, "Probing gxp driver with commit %s\n", GIT_REPO_TAG);
+
gxp = devm_kzalloc(dev, sizeof(*gxp), GFP_KERNEL);
if (!gxp)
return -ENOMEM;
@@ -849,6 +937,8 @@ static int gxp_platform_probe(struct platform_device *pdev)
gxp->misc_dev.name = "gxp";
gxp->misc_dev.fops = &gxp_fops;
+ gxp_wakelock_init(gxp);
+
ret = misc_register(&gxp->misc_dev);
if (ret) {
dev_err(dev, "Failed to register misc device (ret = %d)\n",
@@ -873,14 +963,11 @@ static int gxp_platform_probe(struct platform_device *pdev)
goto err;
}
-#if defined(CONFIG_GXP_CLOUDRIPPER) && !defined(CONFIG_GXP_TEST)
- pm_runtime_enable(dev);
- ret = pm_runtime_get_sync(dev);
+ ret = gxp_pm_init(gxp);
if (ret) {
- dev_err(dev, "pm_runtime_get_sync returned %d\n", ret);
+ dev_err(dev, "Failed to init power management (ret=%d)\n", ret);
goto err;
}
-#endif
#ifndef CONFIG_GXP_USE_SW_MAILBOX
for (i = 0; i < GXP_NUM_CORES; i++) {
@@ -951,11 +1038,11 @@ static int gxp_platform_probe(struct platform_device *pdev)
}
spin_lock_init(&gxp->mailbox_resps_lock);
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
ret = gxp_debug_dump_init(gxp, &gxp_sscd_dev, &gxp_sscd_pdata);
#else
ret = gxp_debug_dump_init(gxp, NULL, NULL);
-#endif // !CONFIG_ANDROID
+#endif // !CONFIG_SUBSYSTEM_COREDUMP
if (ret) {
dev_err(dev, "Failed to initialize debug dump\n");
gxp_debug_dump_exit(gxp);
@@ -986,6 +1073,9 @@ static int gxp_platform_probe(struct platform_device *pdev)
gxp_telemetry_init(gxp);
gxp_create_debugfs(gxp);
gxp_pm_init(gxp);
+ gxp->thermal_mgr = gxp_thermal_init(gxp);
+ if (!gxp->thermal_mgr)
+ dev_err(dev, "Failed to init thermal driver\n");
dev_dbg(dev, "Probe finished\n");
return 0;
@@ -1022,18 +1112,35 @@ static int gxp_platform_remove(struct platform_device *pdev)
#endif
misc_deregister(&gxp->misc_dev);
-#ifdef CONFIG_GXP_CLOUDRIPPER
- // Request to power off BLK_AUR
- gxp_pm_blk_off(gxp);
- pm_runtime_disable(dev);
gxp_pm_destroy(gxp);
-#endif
devm_kfree(dev, (void *)gxp);
return 0;
}
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+
+static int gxp_platform_suspend(struct device *dev)
+{
+ struct gxp_dev *gxp = dev_get_drvdata(dev);
+
+ return gxp_wakelock_suspend(gxp);
+}
+
+static int gxp_platform_resume(struct device *dev)
+{
+ struct gxp_dev *gxp = dev_get_drvdata(dev);
+
+ return gxp_wakelock_resume(gxp);
+}
+
+static const struct dev_pm_ops gxp_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(gxp_platform_suspend, gxp_platform_resume)
+};
+
+#endif /* IS_ENABLED(CONFIG_PM_SLEEP) */
+
#ifdef CONFIG_OF
static const struct of_device_id gxp_of_match[] = {
{ .compatible = "google,gxp", },
@@ -1057,12 +1164,15 @@ static struct platform_driver gxp_platform_driver = {
.name = GXP_DRIVER_NAME,
.of_match_table = of_match_ptr(gxp_of_match),
.acpi_match_table = ACPI_PTR(gxp_acpi_match),
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+ .pm = &gxp_pm_ops,
+#endif
},
};
static int __init gxp_platform_init(void)
{
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
/* Registers SSCD platform device */
if (platform_device_register(&gxp_sscd_dev))
pr_err("Unable to register SSCD platform device\n");
@@ -1073,12 +1183,13 @@ static int __init gxp_platform_init(void)
static void __exit gxp_platform_exit(void)
{
platform_driver_unregister(&gxp_platform_driver);
-#ifdef CONFIG_ANDROID
+#if IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
platform_device_unregister(&gxp_sscd_dev);
#endif
}
MODULE_DESCRIPTION("Google GXP platform driver");
MODULE_LICENSE("GPL v2");
+MODULE_INFO(gitinfo, GIT_REPO_TAG);
module_init(gxp_platform_init);
module_exit(gxp_platform_exit);