summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNrithya Kanakasabapathy <nrithya@google.com>2021-04-13 18:02:09 +0000
committerNrithya Kanakasabapathy <nrithya@google.com>2021-04-16 18:14:28 +0000
commit1e730c79f578b1cea07a44106afb8471c1f7e5f6 (patch)
tree7d077c8703c6a56353da4c74aaaa5cb3dcf8c5dd
parentd3ab4a661f818840430560741576d4d8b68b9d2d (diff)
downloadedgetpu-1e730c79f578b1cea07a44106afb8471c1f7e5f6.tar.gz
Merge branch 'whitechapel' into android-gs-pixel-5.10
* whitechapel: edgetpu: check file op on group join edgetpu: restart firmware on unrecoverable fault notification edgetpu: remove firmware crash extra_info field edgetpu: fix size and offset on host buffer map edgetpu: Create common f/w interface for mobile chipsets edgetpu: remove unbalanced unlock in group alloc edgetpu: abrolhos fix uninit power lock edgetpu: fixup KCI header file comments on response element edgetpu: raise log severity of MMU setup edgetpu: abort probe when MMU setup failed Signed-off-by: Nrithya Kanakasabapathy <nrithya@google.com> Change-Id: I4d968724c8b73a86b607085090289b2845ccfe18
-rw-r--r--drivers/edgetpu/abrolhos-firmware.c26
-rw-r--r--drivers/edgetpu/abrolhos-platform.c11
-rw-r--r--drivers/edgetpu/abrolhos-pm.c5
-rw-r--r--drivers/edgetpu/abrolhos-thermal.c1
-rw-r--r--drivers/edgetpu/edgetpu-core.c15
-rw-r--r--drivers/edgetpu/edgetpu-device-group.c11
-rw-r--r--drivers/edgetpu/edgetpu-fs.c12
-rw-r--r--drivers/edgetpu/edgetpu-internal.h21
-rw-r--r--drivers/edgetpu/edgetpu-kci.c4
-rw-r--r--drivers/edgetpu/edgetpu-kci.h3
-rw-r--r--drivers/edgetpu/mobile-firmware.h54
11 files changed, 122 insertions, 41 deletions
diff --git a/drivers/edgetpu/abrolhos-firmware.c b/drivers/edgetpu/abrolhos-firmware.c
index 2c9b87e..4170c49 100644
--- a/drivers/edgetpu/abrolhos-firmware.c
+++ b/drivers/edgetpu/abrolhos-firmware.c
@@ -9,13 +9,13 @@
#include <linux/gsa/gsa_tpu.h>
#include <linux/slab.h>
-#include "abrolhos-firmware.h"
#include "abrolhos-platform.h"
#include "edgetpu-config.h"
#include "edgetpu-firmware.h"
#include "edgetpu-internal.h"
#include "edgetpu-kci.h"
#include "edgetpu-mailbox.h"
+#include "mobile-firmware.h"
static int abrolhos_firmware_alloc_buffer(
struct edgetpu_firmware *et_fw,
@@ -26,7 +26,7 @@ static int abrolhos_firmware_alloc_buffer(
/* Allocate extra space the image header */
size_t buffer_size =
- edgetpu_pdev->fw_region_size + ABROLHOS_FW_HEADER_SIZE;
+ edgetpu_pdev->fw_region_size + MOBILE_FW_HEADER_SIZE;
fw_buf->vaddr = kzalloc(buffer_size, GFP_KERNEL);
if (!fw_buf->vaddr) {
@@ -70,14 +70,14 @@ static int abrolhos_firmware_prepare_run(struct edgetpu_firmware *et_fw,
struct edgetpu_dev *etdev = et_fw->etdev;
struct abrolhos_platform_dev *edgetpu_pdev = to_abrolhos_dev(etdev);
void *image_vaddr, *header_vaddr;
- struct abrolhos_image_config *image_config;
+ struct mobile_image_config *image_config;
phys_addr_t image_start, image_end, carveout_start, carveout_end;
dma_addr_t header_dma_addr;
int ret, tpu_state;
- if (fw_buf->used_size < ABROLHOS_FW_HEADER_SIZE) {
+ if (fw_buf->used_size < MOBILE_FW_HEADER_SIZE) {
etdev_err(etdev, "Invalid buffer size: %zu < %d\n",
- fw_buf->used_size, ABROLHOS_FW_HEADER_SIZE);
+ fw_buf->used_size, MOBILE_FW_HEADER_SIZE);
return -EINVAL;
}
@@ -109,12 +109,12 @@ static int abrolhos_firmware_prepare_run(struct edgetpu_firmware *et_fw,
}
/* Skip the header */
- memcpy(image_vaddr, fw_buf->vaddr + ABROLHOS_FW_HEADER_SIZE,
- fw_buf->used_size - ABROLHOS_FW_HEADER_SIZE);
+ memcpy(image_vaddr, fw_buf->vaddr + MOBILE_FW_HEADER_SIZE,
+ fw_buf->used_size - MOBILE_FW_HEADER_SIZE);
/* Allocate coherent memory for the image header */
header_vaddr = dma_alloc_coherent(edgetpu_pdev->gsa_dev,
- ABROLHOS_FW_HEADER_SIZE,
+ MOBILE_FW_HEADER_SIZE,
&header_dma_addr, GFP_KERNEL);
if (!header_vaddr) {
etdev_err(etdev,
@@ -123,7 +123,7 @@ static int abrolhos_firmware_prepare_run(struct edgetpu_firmware *et_fw,
goto out_unmap;
}
- memcpy(header_vaddr, fw_buf->vaddr, ABROLHOS_FW_HEADER_SIZE);
+ memcpy(header_vaddr, fw_buf->vaddr, MOBILE_FW_HEADER_SIZE);
etdev_dbg(etdev,
"Requesting GSA image load. meta = %llX payload = %llX",
header_dma_addr, (u64)edgetpu_pdev->fw_region_paddr);
@@ -137,7 +137,7 @@ static int abrolhos_firmware_prepare_run(struct edgetpu_firmware *et_fw,
}
/* fetch the firmware versions */
- image_config = fw_buf->vaddr + ABROLHOS_IMAGE_CONFIG_OFFSET;
+ image_config = fw_buf->vaddr + MOBILE_IMAGE_CONFIG_OFFSET;
memcpy(&etdev->fw_version, &image_config->firmware_versions,
sizeof(etdev->fw_version));
@@ -173,7 +173,7 @@ static int abrolhos_firmware_prepare_run(struct edgetpu_firmware *et_fw,
}
out_free_gsa:
- dma_free_coherent(edgetpu_pdev->gsa_dev, ABROLHOS_FW_HEADER_SIZE,
+ dma_free_coherent(edgetpu_pdev->gsa_dev, MOBILE_FW_HEADER_SIZE,
header_vaddr, header_dma_addr);
out_unmap:
memunmap(image_vaddr);
@@ -188,12 +188,12 @@ static const struct edgetpu_firmware_handlers abrolhos_firmware_handlers = {
.prepare_run = abrolhos_firmware_prepare_run,
};
-int abrolhos_edgetpu_firmware_create(struct edgetpu_dev *etdev)
+int mobile_edgetpu_firmware_create(struct edgetpu_dev *etdev)
{
return edgetpu_firmware_create(etdev, &abrolhos_firmware_handlers);
}
-void abrolhos_edgetpu_firmware_destroy(struct edgetpu_dev *etdev)
+void mobile_edgetpu_firmware_destroy(struct edgetpu_dev *etdev)
{
edgetpu_firmware_destroy(etdev);
}
diff --git a/drivers/edgetpu/abrolhos-platform.c b/drivers/edgetpu/abrolhos-platform.c
index e5e9a94..cc7ea13 100644
--- a/drivers/edgetpu/abrolhos-platform.c
+++ b/drivers/edgetpu/abrolhos-platform.c
@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/types.h>
-#include "abrolhos-firmware.h"
#include "abrolhos-platform.h"
#include "abrolhos-pm.h"
#include "edgetpu-config.h"
@@ -30,6 +29,7 @@
#include "edgetpu-mmu.h"
#include "edgetpu-pm.h"
#include "edgetpu-telemetry.h"
+#include "mobile-firmware.h"
static const struct of_device_id edgetpu_of_match[] = {
{ .compatible = "google,darwinn", },
@@ -172,14 +172,15 @@ static void edgetpu_platform_cleanup_fw_region(
etpdev->shared_mem_vaddr = NULL;
}
-void edgetpu_setup_mmu(struct edgetpu_dev *etdev)
+int edgetpu_setup_mmu(struct edgetpu_dev *etdev)
{
int ret;
/* No MMU info to pass to attach, IOMMU API will handle. */
ret = edgetpu_mmu_attach(etdev, NULL);
if (ret)
- dev_warn(etdev->dev, "failed to attach IOMMU: %d\n", ret);
+ dev_err(etdev->dev, "failed to attach IOMMU: %d\n", ret);
+ return ret;
}
static int abrolhos_parse_ssmt(struct abrolhos_platform_dev *etpdev)
@@ -305,7 +306,7 @@ static int edgetpu_platform_probe(struct platform_device *pdev)
if (ret)
goto out_remove_device;
- ret = abrolhos_edgetpu_firmware_create(&edgetpu_pdev->edgetpu_dev);
+ ret = mobile_edgetpu_firmware_create(&edgetpu_pdev->edgetpu_dev);
if (ret) {
dev_err(dev,
"%s initialize firmware downloader failed: %d\n",
@@ -346,7 +347,7 @@ static int edgetpu_platform_remove(struct platform_device *pdev)
struct edgetpu_dev *etdev = platform_get_drvdata(pdev);
struct abrolhos_platform_dev *edgetpu_pdev = to_abrolhos_dev(etdev);
- abrolhos_edgetpu_firmware_destroy(etdev);
+ mobile_edgetpu_firmware_destroy(etdev);
if (edgetpu_pdev->irq >= 0)
edgetpu_unregister_irq(etdev, edgetpu_pdev->irq);
diff --git a/drivers/edgetpu/abrolhos-pm.c b/drivers/edgetpu/abrolhos-pm.c
index 07f0369..aba134a 100644
--- a/drivers/edgetpu/abrolhos-pm.c
+++ b/drivers/edgetpu/abrolhos-pm.c
@@ -634,13 +634,12 @@ static int abrolhos_pm_after_create(struct edgetpu_pm *etpm)
if (ret)
return ret;
+ mutex_init(&edgetpu_pdev->platform_pwr.policy_lock);
+ mutex_init(&edgetpu_pdev->platform_pwr.state_lock);
ret = abrolhos_pwr_state_set(etdev,
abrolhos_get_initial_pwr_state(dev));
if (ret)
return ret;
-
- mutex_init(&edgetpu_pdev->platform_pwr.policy_lock);
- mutex_init(&edgetpu_pdev->platform_pwr.state_lock);
abrolhos_pwr_debugfs_dir =
debugfs_create_dir("power", edgetpu_fs_debugfs_dir());
if (!abrolhos_pwr_debugfs_dir) {
diff --git a/drivers/edgetpu/abrolhos-thermal.c b/drivers/edgetpu/abrolhos-thermal.c
index cbb9abe..27429a9 100644
--- a/drivers/edgetpu/abrolhos-thermal.c
+++ b/drivers/edgetpu/abrolhos-thermal.c
@@ -16,7 +16,6 @@
#include <linux/version.h>
#include <linux/of.h>
-#include "abrolhos-firmware.h"
#include "abrolhos-platform.h"
#include "abrolhos-pm.h"
#include "edgetpu-config.h"
diff --git a/drivers/edgetpu/edgetpu-core.c b/drivers/edgetpu/edgetpu-core.c
index 891cde6..33ca204 100644
--- a/drivers/edgetpu/edgetpu-core.c
+++ b/drivers/edgetpu/edgetpu-core.c
@@ -31,6 +31,7 @@
#include "edgetpu-mailbox.h"
#include "edgetpu-mcp.h"
#include "edgetpu-mmu.h"
+#include "edgetpu-sw-watchdog.h"
#include "edgetpu-telemetry.h"
#include "edgetpu-usage-stats.h"
#include "edgetpu-wakelock.h"
@@ -256,7 +257,9 @@ int edgetpu_device_add(struct edgetpu_dev *etdev,
etdev->dev_name, ret);
goto remove_dev;
}
- edgetpu_setup_mmu(etdev);
+ ret = edgetpu_setup_mmu(etdev);
+ if (ret)
+ goto remove_dev;
edgetpu_usage_stats_init(etdev);
@@ -443,12 +446,16 @@ void edgetpu_free_coherent(struct edgetpu_dev *etdev,
mem->vaddr = NULL;
}
-void edgetpu_handle_firmware_crash(struct edgetpu_dev *etdev, u16 crash_type,
- u32 extra_info)
+void edgetpu_handle_firmware_crash(struct edgetpu_dev *etdev,
+ enum edgetpu_fw_crash_type crash_type)
{
- etdev_err(etdev, "firmware crashed: %u 0x%x", crash_type, extra_info);
+ etdev_err(etdev, "firmware crashed: %u", crash_type);
etdev->firmware_crash_count++;
edgetpu_fatal_error_notify(etdev);
+
+ if (crash_type == EDGETPU_FW_CRASH_UNRECOV_FAULT)
+ /* Restart firmware without chip reset */
+ edgetpu_watchdog_bite(etdev, false);
}
int __init edgetpu_init(void)
diff --git a/drivers/edgetpu/edgetpu-device-group.c b/drivers/edgetpu/edgetpu-device-group.c
index 94129e1..22ace2b 100644
--- a/drivers/edgetpu/edgetpu-device-group.c
+++ b/drivers/edgetpu/edgetpu-device-group.c
@@ -664,8 +664,6 @@ edgetpu_device_group_alloc(struct edgetpu_client *client,
EDGETPU_CONTEXT_DOMAIN_TOKEN | etdomain->token;
else
group->context_id = EDGETPU_CONTEXT_INVALID;
-
- mutex_unlock(&client->etdev->state_lock);
return group;
error_leave_group:
@@ -1073,9 +1071,14 @@ static struct page **edgetpu_pin_user_pages(struct edgetpu_device_group *group,
int i;
int ret;
- num_pages = size / PAGE_SIZE;
+ if (size == 0)
+ return ERR_PTR(-EINVAL);
offset = host_addr & (PAGE_SIZE - 1);
- if (offset)
+ /* overflow check */
+ if (unlikely(size + offset < size))
+ return ERR_PTR(-ENOMEM);
+ num_pages = (size + offset) / PAGE_SIZE;
+ if ((size + offset) % PAGE_SIZE)
num_pages++;
etdev_dbg(etdev, "%s: hostaddr=0x%llx pages=%u dir=%x", __func__,
diff --git a/drivers/edgetpu/edgetpu-fs.c b/drivers/edgetpu/edgetpu-fs.c
index 9612c97..6742d14 100644
--- a/drivers/edgetpu/edgetpu-fs.c
+++ b/drivers/edgetpu/edgetpu-fs.c
@@ -66,6 +66,11 @@ static struct dentry *edgetpu_debugfs_dir;
} \
} while (0)
+static bool is_edgetpu_file(struct file *file)
+{
+ return file->f_op == &edgetpu_fops;
+}
+
int edgetpu_open(struct edgetpu_dev *etdev, struct file *file)
{
struct edgetpu_client *client;
@@ -254,6 +259,10 @@ static int edgetpu_ioctl_join_group(struct edgetpu_client *client,
ret = -EBADF;
goto out;
}
+ if (!is_edgetpu_file(file)) {
+ ret = -EINVAL;
+ goto out;
+ }
leader = file->private_data;
if (!leader) {
ret = -EINVAL;
@@ -697,9 +706,6 @@ long edgetpu_ioctl(struct file *file, uint cmd, ulong arg)
static long edgetpu_fs_ioctl(struct file *file, uint cmd, ulong arg)
{
- if (file->f_op != &edgetpu_fops)
- return -ENOTTY;
-
return edgetpu_ioctl(file, cmd, arg);
}
diff --git a/drivers/edgetpu/edgetpu-internal.h b/drivers/edgetpu/edgetpu-internal.h
index 9d4f10d..12d47b8 100644
--- a/drivers/edgetpu/edgetpu-internal.h
+++ b/drivers/edgetpu/edgetpu-internal.h
@@ -211,6 +211,15 @@ struct edgetpu_dev {
struct work_struct debug_dump_work;
};
+/* Firmware crash_type codes */
+enum edgetpu_fw_crash_type {
+ EDGETPU_FW_CRASH_ASSERT = 0,
+ EDGETPU_FW_CRASH_DATA_ABORT = 1,
+ EDGETPU_FW_CRASH_PREFETCH_ABORT = 2,
+ EDGETPU_FW_CRASH_UNDEF_EXCEPT = 3,
+ EDGETPU_FW_CRASH_UNRECOV_FAULT = 4,
+};
+
extern const struct file_operations edgetpu_fops;
/* Status regs dump. */
@@ -322,8 +331,8 @@ int edgetpu_open(struct edgetpu_dev *etdev, struct file *file);
long edgetpu_ioctl(struct file *file, uint cmd, ulong arg);
/* Handle firmware crash event */
-void edgetpu_handle_firmware_crash(struct edgetpu_dev *etdev, u16 crash_type,
- u32 extra_info);
+void edgetpu_handle_firmware_crash(struct edgetpu_dev *etdev,
+ enum edgetpu_fw_crash_type crash_type);
/* Bus (Platform/PCI) <-> Core API */
@@ -353,8 +362,12 @@ void edgetpu_chip_exit(struct edgetpu_dev *etdev);
/* IRQ handler */
irqreturn_t edgetpu_chip_irq_handler(int irq, void *arg);
-/* Called from core to chip layer when MMU is needed during device init. */
-void edgetpu_setup_mmu(struct edgetpu_dev *etdev);
+/*
+ * Called from core to chip layer when MMU is needed during device init.
+ *
+ * Returns 0 on success, otherwise -errno.
+ */
+int edgetpu_setup_mmu(struct edgetpu_dev *etdev);
/* Read TPU timestamp */
u64 edgetpu_chip_tpu_timestamp(struct edgetpu_dev *etdev);
diff --git a/drivers/edgetpu/edgetpu-kci.c b/drivers/edgetpu/edgetpu-kci.c
index d48d799..5d00c47 100644
--- a/drivers/edgetpu/edgetpu-kci.c
+++ b/drivers/edgetpu/edgetpu-kci.c
@@ -90,8 +90,8 @@ edgetpu_reverse_kci_consume_response(struct edgetpu_dev *etdev,
switch (resp->code) {
case RKCI_FIRMWARE_CRASH:
- edgetpu_handle_firmware_crash(etdev, resp->status,
- resp->retval);
+ edgetpu_handle_firmware_crash(
+ etdev, (enum edgetpu_fw_crash_type)resp->retval);
break;
default:
etdev_warn(etdev, "%s: Unrecognized KCI request: 0x%x\n",
diff --git a/drivers/edgetpu/edgetpu-kci.h b/drivers/edgetpu/edgetpu-kci.h
index 98a61df..daeafc8 100644
--- a/drivers/edgetpu/edgetpu-kci.h
+++ b/drivers/edgetpu/edgetpu-kci.h
@@ -70,10 +70,9 @@ struct edgetpu_kci_response_element {
u64 seq;
u16 code;
/*
- * Reserved on firmware side for KCI response - they can't touch this.
+ * Reserved for host use - firmware can't touch this.
* If a value is written here it will be discarded and overwritten
* during response processing.
- * For a Reverse KCI command firmware does set this as value1.
*/
u16 status;
/*
diff --git a/drivers/edgetpu/mobile-firmware.h b/drivers/edgetpu/mobile-firmware.h
new file mode 100644
index 0000000..e0c8dd8
--- /dev/null
+++ b/drivers/edgetpu/mobile-firmware.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Implements utilities for firmware management of mobile chipsets.
+ *
+ * Copyright (C) 2021 Google, Inc.
+ */
+#ifndef __MOBILE_FIRMWARE_H__
+#define __MOBILE_FIRMWARE_H__
+
+#include <linux/sizes.h>
+
+#include "edgetpu-internal.h"
+#include "edgetpu.h"
+
+/* mobile FW header size */
+#define MOBILE_FW_HEADER_SIZE SZ_4K
+/* The offset to the signed firmware header. */
+#define MOBILE_HEADER_OFFSET 0x400
+/* The offset to image configuration. */
+#define MOBILE_IMAGE_CONFIG_OFFSET (MOBILE_HEADER_OFFSET + 0x160)
+
+/*
+ * The image configuration attached to the signed firmware.
+ */
+struct mobile_image_config {
+ __u32 carveout_base;
+ __u32 firmware_base;
+ __u32 firmware_size;
+ struct edgetpu_fw_version firmware_versions;
+} __packed;
+
+/*
+ * Mobile firmware header.
+ */
+struct mobile_image_header {
+ char sig[512];
+ char pub[512];
+ int Magic;
+ int Generation;
+ int RollbackInfo;
+ int Length;
+ char Flags[16];
+ char BodyHash[32];
+ char ChipId[32];
+ char AuthConfig[256];
+ struct mobile_image_config ImageConfig;
+};
+
+int mobile_edgetpu_firmware_create(struct edgetpu_dev *etdev);
+void mobile_edgetpu_firmware_destroy(struct edgetpu_dev *etdev);
+
+int mobile_edgetpu_firmware_run_default(struct edgetpu_dev *etdev);
+
+#endif /* __MOBILE_FIRMWARE_H__ */