summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuma copybara merger <zuma-automerger@google.com>2023-02-08 15:32:13 -0800
committerCopybara-Service <copybara-worker@google.com>2023-02-17 18:53:36 -0800
commitc01d777cb9feb30c3ccec179bf5098484294d0eb (patch)
tree0f04e439ce79777370f71afbc1057d899994e397
parent1d82648e250e367df17f452cff31dd320e7396ec (diff)
downloadrio-c01d777cb9feb30c3ccec179bf5098484294d0eb.tar.gz
[Copybara Auto Merge] Merge branch zuma into android14-gs-pixel-5.15
edgetpu: Add PMQoS support Bug: 254703840 Signed-off-by: Zuma copybara merger <zuma-automerger@google.com> GitOrigin-RevId: 0ec4320afeb754d057a1e5d2cade155bb56ef677 Change-Id: Ia0250e3a427013552845e8521a3ba6f6d4c2cc7a
-rw-r--r--drivers/edgetpu/edgetpu-internal.h2
-rw-r--r--drivers/edgetpu/edgetpu-thermal.h17
-rw-r--r--drivers/edgetpu/mobile-thermal.c36
-rw-r--r--drivers/edgetpu/rio-pm.c26
4 files changed, 74 insertions, 7 deletions
diff --git a/drivers/edgetpu/edgetpu-internal.h b/drivers/edgetpu/edgetpu-internal.h
index 798d2d5..fe72da6 100644
--- a/drivers/edgetpu/edgetpu-internal.h
+++ b/drivers/edgetpu/edgetpu-internal.h
@@ -25,6 +25,7 @@
#include <linux/irqreturn.h>
#include <linux/mm_types.h>
#include <linux/mutex.h>
+#include <linux/notifier.h>
#include <linux/refcount.h>
#include <linux/scatterlist.h>
#include <linux/types.h>
@@ -221,6 +222,7 @@ struct edgetpu_dev {
struct work_struct debug_dump_work;
struct mutex freq_lock; /* protects below freq_* variables */
+ struct notifier_block pmqos_nb; /* PMQoS notifier struct */
uint32_t *freq_table; /* Array to record reported frequencies by f/w */
uint32_t freq_count; /* Number of entries in freq_table */
};
diff --git a/drivers/edgetpu/edgetpu-thermal.h b/drivers/edgetpu/edgetpu-thermal.h
index 4efe0fe..f1280a0 100644
--- a/drivers/edgetpu/edgetpu-thermal.h
+++ b/drivers/edgetpu/edgetpu-thermal.h
@@ -27,6 +27,7 @@ struct edgetpu_thermal {
unsigned int tpu_num_states;
struct edgetpu_dev *etdev;
bool thermal_suspended; /* TPU thermal suspended state */
+ unsigned long thermal_vote[2]; /* Thermal vote array, idx0: Tskin; idx1: BCL */
bool enabled;
};
@@ -74,6 +75,22 @@ int edgetpu_thermal_kci_if_powered(struct edgetpu_dev *etdev, u32 state);
int edgetpu_thermal_restore(struct edgetpu_dev *etdev);
/*
+ * Callback for BCL vote for throttling
+ *
+ * This goes through the same path as regular Tskin throttling
+ *
+ * Returns 0 if successful, otherwise negative error.
+ */
+int edgetpu_set_cur_state_bcl(struct thermal_cooling_device *cdev, unsigned long state_original);
+
+/*
+ * API to map frequency to cooling state
+ *
+ * Returns state if successful. On an invalid input it returns lowest state.
+ */
+int edgetpu_state_to_cooling(struct edgetpu_dev *etdev, unsigned long state);
+
+/*
* Holds thermal->lock.
*
* Does nothing if the thermal management is not supported.
diff --git a/drivers/edgetpu/mobile-thermal.c b/drivers/edgetpu/mobile-thermal.c
index d78dc44..34813e9 100644
--- a/drivers/edgetpu/mobile-thermal.c
+++ b/drivers/edgetpu/mobile-thermal.c
@@ -42,10 +42,8 @@ static int edgetpu_get_max_state(struct thermal_cooling_device *cdev, unsigned l
return 0;
}
-/*
- * Set cooling state.
- */
-static int edgetpu_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state_original)
+static int __edgetpu_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state_original, int voter_id)
{
int ret;
struct edgetpu_thermal *thermal = cdev->devdata;
@@ -57,9 +55,12 @@ static int edgetpu_set_cur_state(struct thermal_cooling_device *cdev, unsigned l
return -EINVAL;
}
+ edgetpu_thermal_lock(thermal);
+ thermal->thermal_vote[voter_id] = state_original;
+
+ state_original = max(thermal->thermal_vote[0], thermal->thermal_vote[1]);
state_original = max(thermal->sysfs_req, state_original);
- edgetpu_thermal_lock(thermal);
pwr_state = state_pwr_map[state_original].state;
if (state_original == thermal->cooling_state) {
ret = -EALREADY;
@@ -89,6 +90,19 @@ out:
return ret;
}
+/*
+ * Set cooling state.
+ */
+static int edgetpu_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state_original)
+{
+ return __edgetpu_set_cur_state(cdev, state_original, 0);
+}
+
+int edgetpu_set_cur_state_bcl(struct thermal_cooling_device *cdev, unsigned long state_original)
+{
+ return __edgetpu_set_cur_state(cdev, state_original, 1);
+}
+
static int edgetpu_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state)
{
int ret = 0;
@@ -527,3 +541,15 @@ int edgetpu_thermal_restore(struct edgetpu_dev *etdev)
return ret;
}
+
+int edgetpu_state_to_cooling(struct edgetpu_dev *etdev, unsigned long state)
+{
+ struct edgetpu_thermal *thermal = etdev->thermal;
+ int i = 0;
+
+ for (i = 0; i < thermal->tpu_num_states; i++) {
+ if (state_pwr_map[i].state <= state)
+ return i;
+ }
+ return thermal->tpu_num_states - 1;
+}
diff --git a/drivers/edgetpu/rio-pm.c b/drivers/edgetpu/rio-pm.c
index c013583..81eb133 100644
--- a/drivers/edgetpu/rio-pm.c
+++ b/drivers/edgetpu/rio-pm.c
@@ -7,7 +7,9 @@
#include <linux/delay.h>
#include <linux/iopoll.h>
+#include <linux/notifier.h>
#include <soc/google/bcl.h>
+#include <soc/google/exynos_pm_qos.h>
#include "edgetpu-config.h"
#include "edgetpu-internal.h"
@@ -142,6 +144,22 @@ static int rio_lpm_up(struct edgetpu_dev *etdev)
return 0;
}
+static int rio_pmqos_notifier(struct notifier_block *nb, unsigned long state_freq,
+ void *nb_data)
+{
+ struct edgetpu_dev *etdev;
+ int state_cooling;
+ int ret;
+
+ etdev = container_of(nb, struct edgetpu_dev, pmqos_nb);
+ state_cooling = edgetpu_state_to_cooling(etdev, state_freq);
+ etdev_dbg(etdev, "pmqos req original: %ld, cooling: %d\n", state_freq, state_cooling);
+ ret = edgetpu_set_cur_state_bcl(etdev->thermal->cdev, state_cooling);
+ if (ret)
+ etdev_err_ratelimited(etdev, "Error in BCL throttling %d\n", ret);
+ return NOTIFY_OK;
+}
+
static bool rio_is_block_down(struct edgetpu_dev *etdev)
{
struct edgetpu_mobile_platform_dev *etmdev = to_mobile_dev(etdev);
@@ -162,8 +180,6 @@ static bool rio_is_block_down(struct edgetpu_dev *etdev)
static void rio_post_fw_start(struct edgetpu_dev *etdev)
{
- if (!etdev->soc_data->bcl_dev)
- etdev->soc_data->bcl_dev = google_retrieve_bcl_handle();
if (etdev->soc_data->bcl_dev)
google_init_tpu_ratio(etdev->soc_data->bcl_dev);
}
@@ -179,5 +195,11 @@ int edgetpu_chip_pm_create(struct edgetpu_dev *etdev)
platform_pwr->is_block_down = rio_is_block_down;
platform_pwr->post_fw_start = rio_post_fw_start;
+ etdev->soc_data->bcl_dev = google_retrieve_bcl_handle();
+ if (etdev->soc_data->bcl_dev) {
+ etdev->pmqos_nb.notifier_call = rio_pmqos_notifier;
+ exynos_pm_qos_add_notifier(PM_QOS_TPU_FREQ_MAX, &etdev->pmqos_nb);
+ }
+
return edgetpu_mobile_pm_create(etdev);
}