summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNrithya Kanakasabapathy <nrithya@google.com>2021-04-19 23:06:19 +0000
committerNrithya Kanakasabapathy <nrithya@google.com>2021-04-19 23:06:19 +0000
commitabcce0de883a176e666ef3393594defdab934c86 (patch)
treeb4357dd3a728833aeb1cef99f2b2d9038bb4ebb4
parent1e730c79f578b1cea07a44106afb8471c1f7e5f6 (diff)
downloadabrolhos-abcce0de883a176e666ef3393594defdab934c86.tar.gz
Merge branch 'whitechapel' into android-gs-pixel-5.10
* android-gs-pixel-5.10: edgetpu: add error logs for group finalize failure edgetpu: abrolhos: fix update stats kci req on shutdown. edgetpu: abrolhos: initialize clock divider ratios edgetpu: add common sysfs watchdog_timeout_count attr edgetpu: remove secure IOMMU SMC edgetpu: add optional wrapper class for validating edgetpu fds Signed-off-by: Nrithya Kanakasabapathy <nrithya@google.com> Change-Id: Id4aff09f9fe65deaec60b670914e10e16af50d92
-rw-r--r--drivers/edgetpu/Kconfig18
-rw-r--r--drivers/edgetpu/abrolhos-platform.h2
-rw-r--r--drivers/edgetpu/abrolhos-pm.c32
-rw-r--r--drivers/edgetpu/edgetpu-device-group.c45
-rw-r--r--drivers/edgetpu/edgetpu-firmware.c1
-rw-r--r--drivers/edgetpu/edgetpu-fs.c13
-rw-r--r--drivers/edgetpu/edgetpu-internal.h10
-rw-r--r--drivers/edgetpu/edgetpu-kci.c26
-rw-r--r--drivers/edgetpu/edgetpu-kci.h10
-rw-r--r--drivers/edgetpu/edgetpu-mapping.h11
10 files changed, 126 insertions, 42 deletions
diff --git a/drivers/edgetpu/Kconfig b/drivers/edgetpu/Kconfig
index 3105089..fe40029 100644
--- a/drivers/edgetpu/Kconfig
+++ b/drivers/edgetpu/Kconfig
@@ -21,6 +21,24 @@ config ABROLHOS
To compile this driver as a module, choose M here. The module
will be called "abrolhos".
+config EDGETPU_EXTERNAL_WRAPPER_CLASS
+ bool "EdgeTPU add external wrapper class"
+ depends on EDGETPU_FRAMEWORK
+ default n
+ help
+ Selected if an external wrapper class is to be used. This option is
+ intended to be auto-selected by other config options that depend on
+ external classes that wrap the EdgeTPU core driver and is not
+ intended for interactive use.
+
+config EDGETPU_FPGA
+ bool "Build for EdgeTPU chip FPGA emulation"
+ depends on EDGETPU_FRAMEWORK
+ default n
+ help
+ Say Y to build for HAPS/Palladium/etc. FPGA emulators, or N to build
+ silicon with full number of tiles.
+
config EDGETPU_TELEMETRY_TRACE
bool "Build EdgeTPU driver with firmware tracing support"
depends on EDGETPU_FRAMEWORK
diff --git a/drivers/edgetpu/abrolhos-platform.h b/drivers/edgetpu/abrolhos-platform.h
index 721f24d..980dc8e 100644
--- a/drivers/edgetpu/abrolhos-platform.h
+++ b/drivers/edgetpu/abrolhos-platform.h
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <soc/google/bcl.h>
#include "abrolhos-debug-dump.h"
#include "abrolhos-pm.h"
@@ -44,6 +45,7 @@ struct abrolhos_platform_dev {
struct edgetpu_coherent_mem log_mem;
struct edgetpu_coherent_mem trace_mem;
struct abrolhos_sscd_info sscd_info;
+ struct gs101_bcl_dev *bcl_dev;
};
#endif /* __ABROLHOS_PLATFORM_H__ */
diff --git a/drivers/edgetpu/abrolhos-pm.c b/drivers/edgetpu/abrolhos-pm.c
index aba134a..47fa7dc 100644
--- a/drivers/edgetpu/abrolhos-pm.c
+++ b/drivers/edgetpu/abrolhos-pm.c
@@ -10,7 +10,9 @@
#include <linux/gsa/gsa_tpu.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
-#include <linux/soc/samsung/exynos-smc.h>
+#include <soc/google/bcl.h>
+#include <soc/google/bts.h>
+#include <soc/google/exynos_pm_qos.h>
#include "abrolhos-platform.h"
#include "abrolhos-pm.h"
@@ -22,13 +24,8 @@
#include "edgetpu-pm.h"
#include "edgetpu-telemetry.h"
-#include "soc/google/exynos_pm_qos.h"
-#include "soc/google/bts.h"
-
#include "edgetpu-pm.c"
-#define TPU_SMC_ID (0x15)
-
/*
* Encode INT/MIF values as a 16 bit pair in the 32-bit return value
* (in units of MHz, to provide enough range)
@@ -98,12 +95,6 @@ static int abrolhos_pwr_state_set_locked(void *data, u64 val)
dev_err(dev, "pm_runtime_get_sync returned %d\n", ret);
return ret;
}
- ret = exynos_smc(SMC_PROTECTION_SET, 0, TPU_SMC_ID,
- SMC_PROTECTION_ENABLE);
- if (ret)
- dev_warn(dev,
- "exynos_smc protection enable returned %d\n",
- ret);
}
ret = exynos_acpm_set_rate(TPU_ACPM_DOMAIN, (unsigned long)val);
@@ -114,13 +105,6 @@ static int abrolhos_pwr_state_set_locked(void *data, u64 val)
}
if (curr_state != TPU_OFF && val == TPU_OFF) {
- ret = exynos_smc(SMC_PROTECTION_SET, 0, TPU_SMC_ID,
- SMC_PROTECTION_DISABLE);
- if (ret)
- dev_warn(dev,
- "exynos_smc protection disable returned %d\n",
- ret);
-
ret = pm_runtime_put_sync(dev);
if (ret) {
dev_err(dev, "%s: pm_runtime_put_sync returned %d\n",
@@ -522,8 +506,14 @@ static int abrolhos_power_up(struct edgetpu_pm *etpm)
etdev->state = ETDEV_STATE_GOOD; /* f/w handshake success */
mutex_unlock(&etdev->state_lock);
- if (ret)
+ if (ret) {
abrolhos_power_down(etpm);
+ } else {
+ if (!edgetpu_pdev->bcl_dev)
+ edgetpu_pdev->bcl_dev = gs101_retrieve_bcl_handle();
+ if (edgetpu_pdev->bcl_dev)
+ gs101_init_tpu_ratio(edgetpu_pdev->bcl_dev);
+ }
return ret;
}
@@ -611,7 +601,7 @@ static void abrolhos_power_down(struct edgetpu_pm *etpm)
if (etdev->kci && edgetpu_firmware_status_locked(etdev) == FW_VALID) {
/* Update usage stats before we power off fw. */
- edgetpu_kci_update_usage(etdev);
+ edgetpu_kci_update_usage_locked(etdev);
abrolhos_pm_shutdown_firmware(edgetpu_pdev, etdev,
edgetpu_pdev);
edgetpu_kci_cancel_work_queues(etdev->kci);
diff --git a/drivers/edgetpu/edgetpu-device-group.c b/drivers/edgetpu/edgetpu-device-group.c
index 22ace2b..5e2a9d0 100644
--- a/drivers/edgetpu/edgetpu-device-group.c
+++ b/drivers/edgetpu/edgetpu-device-group.c
@@ -216,18 +216,26 @@ edgetpu_device_group_kci_finalized(struct edgetpu_device_group *group)
*/
if (etdev->state != ETDEV_STATE_GOOD) {
ret = edgetpu_get_state_errno_locked(etdev);
+ etdev_err(group->etdev, "finalize dev %s state %u (%d)",
+ etdev->dev_name, etdev->state, ret);
goto out_free;
}
ret = edgetpu_async_add_job(
ctx, &params[i],
(edgetpu_async_job_t)edgetpu_kci_join_group_worker);
- if (ret)
+ if (ret) {
+ etdev_err(group->etdev,
+ "finalize fw job for %s returns %d",
+ etdev->dev_name, ret);
goto out_free;
+ }
atomic_inc(&etdev->job_count);
}
ret = edgetpu_async_wait(ctx);
- if (ret)
+ if (ret) {
+ etdev_err(group->etdev, "finalize wait returns %d", ret);
goto out_free;
+ }
for_each_async_ret(ctx, val, i) {
if (val)
goto out_leave;
@@ -471,11 +479,21 @@ static bool edgetpu_group_check_contiguity(struct edgetpu_device_group *group)
mcp_n = mcp->total_num;
fr = group->etdev->mcp_die_index;
for (i = 1; i < group->n_clients; i++, fr = to) {
- to = edgetpu_device_group_nth_etdev(group, i)->mcp_die_index;
+ struct edgetpu_dev *to_etdev =
+ edgetpu_device_group_nth_etdev(group, i);
+
+ to = to_etdev->mcp_die_index;
if (fr + 1 == to)
continue;
- if (!mcp_n || (fr + 1) % mcp_n != to)
+ if (!mcp_n || (fr + 1) % mcp_n != to) {
+ struct edgetpu_dev *fr_etdev =
+ edgetpu_device_group_nth_etdev(group, i - 1);
+
+ etdev_err(group->etdev,
+ "finalize group not contiguous at %s -> %s",
+ fr_etdev->dev_name, to_etdev->dev_name);
return false;
+ }
}
return true;
@@ -749,13 +767,17 @@ int edgetpu_device_group_finalize(struct edgetpu_device_group *group)
goto err_unlock;
if (!edgetpu_device_group_is_waiting(group)) {
+ etdev_err(group->etdev, "finalize group is not waiting");
ret = -EINVAL;
goto err_unlock;
}
ret = group_alloc_members(group);
- if (ret)
+ if (ret) {
+ etdev_err(group->etdev,
+ "finalize alloc members returns %d", ret);
goto err_unlock;
+ }
/*
* Check the contiguity here but not in edgetpu_clients_groupable()
@@ -780,20 +802,25 @@ int edgetpu_device_group_finalize(struct edgetpu_device_group *group)
ret = do_attach_mailbox_locked(group);
if (ret) {
etdev_err(group->etdev,
- "attach mailbox failed on finalization: %d",
- ret);
+ "finalize attach mailbox failed: %d", ret);
goto err_release_members;
}
}
#ifdef EDGETPU_HAS_P2P_MAILBOX
ret = edgetpu_p2p_mailbox_setup(group);
- if (ret)
+ if (ret) {
+ etdev_err(group->etdev,
+ "finalize p2p mailbox setup failed: %d", ret);
goto err_detach_mailbox;
+ }
#endif
ret = edgetpu_group_setup_remote_dram(group);
- if (ret)
+ if (ret) {
+ etdev_err(group->etdev,
+ "finalize remote dram setup failed: %d", ret);
goto err_release_p2p;
+ }
edgetpu_usr_init_group(group);
diff --git a/drivers/edgetpu/edgetpu-firmware.c b/drivers/edgetpu/edgetpu-firmware.c
index a4ac9a5..673a51c 100644
--- a/drivers/edgetpu/edgetpu-firmware.c
+++ b/drivers/edgetpu/edgetpu-firmware.c
@@ -659,6 +659,7 @@ static void edgetpu_firmware_wdt_timeout_action(void *data)
struct edgetpu_dev *etdev = data;
struct edgetpu_firmware *et_fw = etdev->firmware;
+ etdev->watchdog_timeout_count++;
/* Don't attempt f/w restart if device is off. */
if (!edgetpu_is_powered(etdev))
return;
diff --git a/drivers/edgetpu/edgetpu-fs.c b/drivers/edgetpu/edgetpu-fs.c
index 6742d14..3966226 100644
--- a/drivers/edgetpu/edgetpu-fs.c
+++ b/drivers/edgetpu/edgetpu-fs.c
@@ -68,6 +68,8 @@ static struct dentry *edgetpu_debugfs_dir;
static bool is_edgetpu_file(struct file *file)
{
+ if (edgetpu_is_external_wrapper_class_file(file))
+ return true;
return file->f_op == &edgetpu_fops;
}
@@ -911,8 +913,19 @@ static ssize_t firmware_crash_count_show(
}
static DEVICE_ATTR_RO(firmware_crash_count);
+static ssize_t watchdog_timeout_count_show(
+ struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct edgetpu_dev *etdev = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", etdev->watchdog_timeout_count);
+}
+static DEVICE_ATTR_RO(watchdog_timeout_count);
+
static struct attribute *edgetpu_dev_attrs[] = {
&dev_attr_firmware_crash_count.attr,
+ &dev_attr_watchdog_timeout_count.attr,
NULL,
};
diff --git a/drivers/edgetpu/edgetpu-internal.h b/drivers/edgetpu/edgetpu-internal.h
index 12d47b8..1a8cc35 100644
--- a/drivers/edgetpu/edgetpu-internal.h
+++ b/drivers/edgetpu/edgetpu-internal.h
@@ -204,6 +204,7 @@ struct edgetpu_dev {
/* counts of error events */
uint firmware_crash_count;
+ uint watchdog_timeout_count;
struct edgetpu_coherent_mem debug_dump_mem; /* debug dump memory */
/* debug dump handlers */
@@ -330,6 +331,15 @@ void edgetpu_free_coherent(struct edgetpu_dev *etdev,
int edgetpu_open(struct edgetpu_dev *etdev, struct file *file);
long edgetpu_ioctl(struct file *file, uint cmd, ulong arg);
+#if IS_ENABLED(CONFIG_EDGETPU_EXTERNAL_WRAPPER_CLASS)
+extern bool edgetpu_is_external_wrapper_class_file(struct file *file);
+#else
+static inline bool edgetpu_is_external_wrapper_class_file(struct file *file)
+{
+ return false;
+}
+#endif
+
/* Handle firmware crash event */
void edgetpu_handle_firmware_crash(struct edgetpu_dev *etdev,
enum edgetpu_fw_crash_type crash_type);
diff --git a/drivers/edgetpu/edgetpu-kci.c b/drivers/edgetpu/edgetpu-kci.c
index 5d00c47..c8b5d86 100644
--- a/drivers/edgetpu/edgetpu-kci.c
+++ b/drivers/edgetpu/edgetpu-kci.c
@@ -842,6 +842,22 @@ enum edgetpu_fw_flavor edgetpu_kci_fw_info(struct edgetpu_kci *kci,
int edgetpu_kci_update_usage(struct edgetpu_dev *etdev)
{
+ int ret;
+
+ /* Quick return if device already powered down, else get PM ref. */
+ if (!edgetpu_is_powered(etdev))
+ return -EAGAIN;
+ ret = edgetpu_pm_get(etdev->pm);
+ if (ret)
+ return ret;
+ ret = edgetpu_kci_update_usage_locked(etdev);
+
+ edgetpu_pm_put(etdev->pm);
+ return ret;
+}
+
+int edgetpu_kci_update_usage_locked(struct edgetpu_dev *etdev)
+{
#define EDGETPU_USAGE_BUFFER_SIZE 4096
struct edgetpu_command_element cmd = {
.code = KCI_CODE_GET_USAGE,
@@ -854,19 +870,13 @@ int edgetpu_kci_update_usage(struct edgetpu_dev *etdev)
struct edgetpu_kci_response_element resp;
int ret;
- /* Quick return if device already powered down, else get PM ref. */
- if (!edgetpu_is_powered(etdev))
- return -EAGAIN;
- ret = edgetpu_pm_get(etdev->pm);
- if (ret)
- return ret;
ret = edgetpu_iremap_alloc(etdev, EDGETPU_USAGE_BUFFER_SIZE, &mem,
EDGETPU_CONTEXT_KCI);
if (ret) {
etdev_warn_once(etdev, "%s: failed to allocate usage buffer",
__func__);
- goto out;
+ return ret;
}
cmd.dma.address = mem.tpu_addr;
@@ -883,8 +893,6 @@ int edgetpu_kci_update_usage(struct edgetpu_dev *etdev)
edgetpu_iremap_free(etdev, &mem, EDGETPU_CONTEXT_KCI);
-out:
- edgetpu_pm_put(etdev->pm);
return ret;
}
diff --git a/drivers/edgetpu/edgetpu-kci.h b/drivers/edgetpu/edgetpu-kci.h
index daeafc8..443c690 100644
--- a/drivers/edgetpu/edgetpu-kci.h
+++ b/drivers/edgetpu/edgetpu-kci.h
@@ -287,6 +287,16 @@ enum edgetpu_fw_flavor edgetpu_kci_fw_info(
int edgetpu_kci_update_usage(struct edgetpu_dev *etdev);
/*
+ * Works the same as edgetpu_kci_update_usage() except the caller of this
+ * function must guarantee the device stays powered up, typically by calling
+ * edgetpu_pm_get() or by calling this function from the power management
+ * functions themselves.
+ *
+ * Returns KCI response code on success or < 0 on error (typically -ETIMEDOUT).
+ */
+int edgetpu_kci_update_usage_locked(struct edgetpu_dev *etdev);
+
+/*
* Sends the "Map Log Buffer" command and waits for remote response.
*
* Returns the code of response, or a negative errno on error.
diff --git a/drivers/edgetpu/edgetpu-mapping.h b/drivers/edgetpu/edgetpu-mapping.h
index 35906b0..6681427 100644
--- a/drivers/edgetpu/edgetpu-mapping.h
+++ b/drivers/edgetpu/edgetpu-mapping.h
@@ -141,13 +141,18 @@ void edgetpu_mappings_show(struct edgetpu_mapping_root *mappings,
static inline int __dma_dir_to_iommu_prot(enum dma_data_direction dir)
{
+ int prot = 0;
+
+#ifdef EDGETPU_IS_IO_COHERENT
+ prot = IOMMU_CACHE;
+#endif
switch (dir) {
case DMA_BIDIRECTIONAL:
- return IOMMU_READ | IOMMU_WRITE;
+ return prot | IOMMU_READ | IOMMU_WRITE;
case DMA_TO_DEVICE:
- return IOMMU_READ;
+ return prot | IOMMU_READ;
case DMA_FROM_DEVICE:
- return IOMMU_WRITE;
+ return prot | IOMMU_WRITE;
default:
return 0;
}