diff options
author | Nrithya Kanakasabapathy <nrithya@google.com> | 2021-04-13 18:02:09 +0000 |
---|---|---|
committer | Nrithya Kanakasabapathy <nrithya@google.com> | 2021-04-16 18:14:28 +0000 |
commit | 1e730c79f578b1cea07a44106afb8471c1f7e5f6 (patch) | |
tree | 7d077c8703c6a56353da4c74aaaa5cb3dcf8c5dd | |
parent | d3ab4a661f818840430560741576d4d8b68b9d2d (diff) | |
download | edgetpu-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.c | 26 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-platform.c | 11 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-pm.c | 5 | ||||
-rw-r--r-- | drivers/edgetpu/abrolhos-thermal.c | 1 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-core.c | 15 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-device-group.c | 11 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-fs.c | 12 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-internal.h | 21 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-kci.c | 4 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-kci.h | 3 | ||||
-rw-r--r-- | drivers/edgetpu/mobile-firmware.h | 54 |
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__ */ |