From abcce0de883a176e666ef3393594defdab934c86 Mon Sep 17 00:00:00 2001 From: Nrithya Kanakasabapathy Date: Mon, 19 Apr 2021 23:06:19 +0000 Subject: 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 Change-Id: Id4aff09f9fe65deaec60b670914e10e16af50d92 --- drivers/edgetpu/Kconfig | 18 ++++++++++++++ drivers/edgetpu/abrolhos-platform.h | 2 ++ drivers/edgetpu/abrolhos-pm.c | 32 +++++++++--------------- drivers/edgetpu/edgetpu-device-group.c | 45 +++++++++++++++++++++++++++------- drivers/edgetpu/edgetpu-firmware.c | 1 + drivers/edgetpu/edgetpu-fs.c | 13 ++++++++++ drivers/edgetpu/edgetpu-internal.h | 10 ++++++++ drivers/edgetpu/edgetpu-kci.c | 26 +++++++++++++------- drivers/edgetpu/edgetpu-kci.h | 10 ++++++++ drivers/edgetpu/edgetpu-mapping.h | 11 ++++++--- 10 files changed, 126 insertions(+), 42 deletions(-) (limited to 'drivers') 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 #include #include +#include #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 #include #include -#include +#include +#include +#include #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, ¶ms[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 @@ -841,6 +841,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 = { @@ -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 @@ -286,6 +286,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. * 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; } -- cgit v1.2.3