summaryrefslogtreecommitdiff
path: root/gxp-firmware-data.c
diff options
context:
space:
mode:
Diffstat (limited to 'gxp-firmware-data.c')
-rw-r--r--gxp-firmware-data.c847
1 files changed, 74 insertions, 773 deletions
diff --git a/gxp-firmware-data.c b/gxp-firmware-data.c
index 4a35ccc..841e80e 100644
--- a/gxp-firmware-data.c
+++ b/gxp-firmware-data.c
@@ -5,93 +5,30 @@
* Copyright (C) 2021 Google LLC
*/
-#include <linux/bitops.h>
-#include <linux/dma-mapping.h>
-#include <linux/genalloc.h>
+#include <linux/slab.h>
+#include "gxp-config.h"
#include "gxp-debug-dump.h"
#include "gxp-firmware-data.h"
#include "gxp-firmware.h" /* gxp_core_boot */
#include "gxp-host-device-structs.h"
#include "gxp-internal.h"
-#include "gxp-range-alloc.h"
#include "gxp-vd.h"
#include "gxp.h"
-/*
- * The minimum alignment order (power of 2) of allocations in the firmware data
- * region.
- */
-#define FW_DATA_STORAGE_ORDER 3
-
/* A byte pattern to pre-populate the FW region with */
#define FW_DATA_DEBUG_PATTERN 0x66
-/* IDs for dedicated doorbells used by some system components */
-#define DOORBELL_ID_CORE_WAKEUP(__core__) (0 + __core__)
-
-/* IDs for dedicated sync barriers used by some system components */
-#define SYNC_BARRIER_ID_UART 1
-
/* Default application parameters */
#define DEFAULT_APP_ID 1
-#define DEFAULT_APP_USER_MEM_SIZE (120 * 1024)
-#define DEFAULT_APP_USER_MEM_ALIGNMENT 8
-#define DEFAULT_APP_THREAD_COUNT 2
-#define DEFAULT_APP_TCM_PER_BANK (100 * 1024)
-#define DEFAULT_APP_USER_DOORBELL_COUNT 2
-#define DEFAULT_APP_USER_BARRIER_COUNT 2
-
-/* Core-to-core mailbox communication constants */
-#define CORE_TO_CORE_MBX_CMD_COUNT 10
-#define CORE_TO_CORE_MBX_RSP_COUNT 10
-
-/* A block allocator managing and partitioning a memory region for device use */
-struct fw_memory_allocator {
- struct gen_pool *pool;
- struct gxp_dev *gxp;
- void *base_host_addr;
- uint32_t base_device_addr;
-};
-
-/* A memory region allocated for device use */
-struct fw_memory {
- void *host_addr;
- uint32_t device_addr;
- size_t sz;
-};
/*
* Holds information about system-wide HW and memory resources given to the FWs
* of GXP devices.
*/
struct gxp_fw_data_manager {
- /* Host-side pointers for book keeping */
- void *fw_data_virt;
- struct gxp_system_descriptor *system_desc;
-
- /* Doorbells allocator and reserved doorbell IDs */
- struct range_alloc *doorbell_allocator;
- int core_wakeup_doorbells[GXP_NUM_WAKEUP_DOORBELLS];
- int semaphore_doorbells[GXP_NUM_CORES];
-
- /* Sync barriers allocator and reserved sync barrier IDs */
- struct range_alloc *sync_barrier_allocator;
- int uart_sync_barrier;
- int timer_regions_barrier;
- int watchdog_region_barrier;
- int uart_region_barrier;
- int doorbell_regions_barrier;
- int sync_barrier_regions_barrier;
- int semaphores_regions_barrier;
-
- /* System-wide device memory resources */
- struct fw_memory_allocator *allocator;
- struct fw_memory sys_desc_mem;
- struct fw_memory wdog_mem;
- struct fw_memory core_telemetry_mem;
- struct fw_memory debug_dump_mem;
-
+ /* Cached core telemetry descriptors. */
+ struct gxp_core_telemetry_descriptor core_telemetry_desc;
/*
* A host-view of the System configuration descriptor. This same desc
* is provided to all VDs and all cores. This is the R/O section.
@@ -104,477 +41,6 @@ struct gxp_fw_data_manager {
struct gxp_system_descriptor_rw *sys_desc_rw;
};
-/* A container holding information for a single GXP application. */
-struct app_metadata {
- struct gxp_fw_data_manager *mgr;
- struct gxp_virtual_device *vd;
- uint application_id;
- uint core_count;
- uint core_list; /* bitmap of cores allocated to this app */
-
- /* Per-app doorbell IDs */
- int user_doorbells_count;
- int *user_doorbells;
-
- /* Per-app sync barrier IDs */
- int user_barriers_count;
- int *user_barriers;
-
- /* Per-app memory regions */
- struct fw_memory user_mem;
- struct fw_memory doorbells_mem;
- struct fw_memory sync_barriers_mem;
- struct fw_memory semaphores_mem;
- struct fw_memory cores_mem;
- struct fw_memory core_cmd_queues_mem[GXP_NUM_CORES];
- struct fw_memory core_rsp_queues_mem[GXP_NUM_CORES];
- struct fw_memory app_mem;
-};
-
-static struct fw_memory_allocator *mem_alloc_create(struct gxp_dev *gxp,
- void *host_base,
- uint32_t device_base,
- size_t size)
-{
- struct fw_memory_allocator *allocator;
- int ret = 0;
-
- allocator = kzalloc(sizeof(*allocator), GFP_KERNEL);
- if (!allocator)
- return ERR_PTR(-ENOMEM);
-
- /*
- * Use a genpool to allocate and free chunks of the virtual address
- * space reserved for FW data. The genpool doesn't use the passed
- * addresses internally to access any data, thus it is safe to use it to
- * manage memory that the host may not be able to access directly.
- * The allocator also records the host-side address so that the code
- * here can access and populate data in this region.
- */
- allocator->gxp = gxp;
- allocator->pool = gen_pool_create(FW_DATA_STORAGE_ORDER, /*nid=*/-1);
- if (!allocator->pool) {
- dev_err(gxp->dev, "Failed to create memory pool\n");
- kfree(allocator);
- return ERR_PTR(-ENOMEM);
- }
-
- ret = gen_pool_add(allocator->pool, device_base, size, /*nid=*/-1);
- if (ret) {
- dev_err(gxp->dev, "Failed to add memory to pool (ret = %d)\n",
- ret);
- gen_pool_destroy(allocator->pool);
- kfree(allocator);
- return ERR_PTR(ret);
- }
- allocator->base_host_addr = host_base;
- allocator->base_device_addr = device_base;
-
- return allocator;
-}
-
-static int mem_alloc_allocate(struct fw_memory_allocator *allocator,
- struct fw_memory *mem, size_t size,
- uint8_t alignment)
-{
- struct genpool_data_align data = { .align = alignment };
- uint32_t dev_addr;
-
- dev_addr = gen_pool_alloc_algo(allocator->pool, size,
- gen_pool_first_fit_align, &data);
- if (!dev_addr)
- return -ENOMEM;
-
- mem->host_addr = allocator->base_host_addr +
- (dev_addr - allocator->base_device_addr);
- mem->device_addr = dev_addr;
- mem->sz = size;
-
- return 0;
-}
-
-static void mem_alloc_free(struct fw_memory_allocator *allocator,
- struct fw_memory *mem)
-{
- gen_pool_free(allocator->pool, mem->device_addr, mem->sz);
-}
-
-static void mem_alloc_destroy(struct fw_memory_allocator *allocator)
-{
- WARN_ON(gen_pool_avail(allocator->pool) !=
- gen_pool_size(allocator->pool));
- gen_pool_destroy(allocator->pool);
- kfree(allocator);
-}
-
-static struct fw_memory init_doorbells(struct app_metadata *app)
-{
- struct gxp_doorbells_descriptor *db_region;
- struct fw_memory mem;
- uint32_t mem_size;
- uint32_t doorbell_count;
- int i;
-
- doorbell_count = app->user_doorbells_count;
- mem_size = sizeof(*db_region) +
- doorbell_count * sizeof(db_region->doorbells[0]);
-
- mem_alloc_allocate(app->mgr->allocator, &mem, mem_size,
- __alignof__(struct gxp_doorbells_descriptor));
-
- db_region = mem.host_addr;
- db_region->application_id = app->application_id;
- db_region->protection_barrier = app->mgr->doorbell_regions_barrier;
- db_region->num_items = doorbell_count;
- for (i = 0; i < doorbell_count; i++) {
- db_region->doorbells[i].users_count = 0;
- db_region->doorbells[i].hw_doorbell_idx =
- app->user_doorbells[i];
- }
-
- return mem;
-}
-
-static struct fw_memory init_sync_barriers(struct app_metadata *app)
-{
- struct gxp_sync_barriers_descriptor *sb_region;
- struct fw_memory mem;
- uint32_t mem_size;
- uint32_t barrier_count;
- int i;
-
- barrier_count = app->user_barriers_count;
- mem_size = sizeof(*sb_region) +
- barrier_count * sizeof(sb_region->barriers[0]);
-
- mem_alloc_allocate(app->mgr->allocator, &mem, mem_size,
- __alignof__(struct gxp_sync_barriers_descriptor));
-
- sb_region = mem.host_addr;
- sb_region->application_id = app->application_id;
- sb_region->protection_barrier = app->mgr->sync_barrier_regions_barrier;
- sb_region->num_items = barrier_count;
- for (i = 0; i < barrier_count; i++) {
- sb_region->barriers[i].users_count = 0;
- sb_region->barriers[i].hw_barrier_idx = app->user_barriers[i];
- }
-
- return mem;
-}
-
-static struct fw_memory init_watchdog(struct gxp_fw_data_manager *mgr)
-{
- struct gxp_watchdog_descriptor *wd_region;
- struct fw_memory mem;
-
- mem_alloc_allocate(mgr->allocator, &mem, sizeof(*wd_region),
- __alignof__(struct gxp_watchdog_descriptor));
-
- wd_region = mem.host_addr;
- wd_region->protection_barrier = mgr->watchdog_region_barrier;
- wd_region->target_value = 0;
- wd_region->participating_cores = 0;
- wd_region->responded_cores = 0;
- wd_region->tripped = 0;
-
- return mem;
-}
-
-static struct fw_memory init_core_telemetry(struct gxp_fw_data_manager *mgr)
-{
- struct gxp_core_telemetry_descriptor *tel_region;
- struct fw_memory mem;
-
- mem_alloc_allocate(mgr->allocator, &mem, sizeof(*tel_region),
- __alignof__(struct gxp_core_telemetry_descriptor));
-
- tel_region = mem.host_addr;
-
- /*
- * Core telemetry is disabled for now.
- * Subsuequent calls to the FW data module can be used to populate or
- * depopulate the descriptor pointers on demand.
- */
- memset(tel_region, 0x00, sizeof(*tel_region));
-
- return mem;
-}
-
-static struct fw_memory init_debug_dump(struct gxp_dev *gxp)
-{
- struct fw_memory mem;
-
- if (gxp->debug_dump_mgr) {
- mem.host_addr = gxp->debug_dump_mgr->buf.vaddr;
- mem.device_addr = gxp->debug_dump_mgr->buf.dsp_addr;
- mem.sz = gxp->debug_dump_mgr->buf.size;
- } else {
- mem.host_addr = 0;
- mem.device_addr = 0;
- mem.sz = 0;
- }
-
- return mem;
-}
-
-static struct fw_memory init_app_user_memory(struct app_metadata *app,
- int memory_size)
-{
- struct fw_memory mem;
-
- mem_alloc_allocate(app->mgr->allocator, &mem, memory_size,
- DEFAULT_APP_USER_MEM_ALIGNMENT);
-
- return mem;
-}
-
-static struct fw_memory init_app_semaphores(struct app_metadata *app)
-{
- struct gxp_semaphores_descriptor *sm_region;
- struct fw_memory mem;
- uint32_t mem_size;
- uint32_t semaphore_count;
- int core;
- int i;
-
- semaphore_count = NUM_SYSTEM_SEMAPHORES;
- mem_size = sizeof(*sm_region) +
- semaphore_count * sizeof(sm_region->semaphores[0]);
-
- mem_alloc_allocate(app->mgr->allocator, &mem, mem_size,
- __alignof__(struct gxp_semaphores_descriptor));
-
- sm_region = mem.host_addr;
- sm_region->application_id = app->application_id;
- sm_region->protection_barrier = app->mgr->semaphores_regions_barrier;
-
- core = 0;
- for (i = 0; i < GXP_NUM_CORES; i++) {
- if (app->core_list & BIT(i))
- sm_region->wakeup_doorbells[core++] =
- app->mgr->semaphore_doorbells[i];
- sm_region->woken_pending_semaphores[i] = 0;
- }
-
- sm_region->num_items = semaphore_count;
- for (i = 0; i < semaphore_count; i++) {
- sm_region->semaphores[i].users_count = 0;
- sm_region->semaphores[i].count = 0;
- sm_region->semaphores[i].waiters = 0;
- }
-
- return mem;
-}
-
-static struct fw_memory init_app_cores(struct app_metadata *app)
-{
- struct gxp_cores_descriptor *cd_region;
- struct gxp_queue_info *q_info;
- struct fw_memory mem;
- uint32_t mem_size;
- int semaphore_id;
- int core_count;
- int i;
- const int cmd_queue_items = CORE_TO_CORE_MBX_CMD_COUNT;
- const int resp_queue_items = CORE_TO_CORE_MBX_RSP_COUNT;
-
- /* Core info structures. */
- core_count = app->core_count;
- mem_size =
- sizeof(*cd_region) + core_count * sizeof(cd_region->cores[0]);
-
- mem_alloc_allocate(app->mgr->allocator, &mem, mem_size,
- __alignof__(struct gxp_cores_descriptor));
-
- cd_region = mem.host_addr;
- cd_region->num_items = core_count;
-
- /* Command and response queues. */
- semaphore_id = 0;
- for (i = 0; i < core_count; i++) {
- /* Allocate per-core command queue storage. */
- mem_size = cmd_queue_items *
- sizeof(struct gxp_core_to_core_command);
- mem_alloc_allocate(
- app->mgr->allocator, &app->core_cmd_queues_mem[i],
- mem_size, __alignof__(struct gxp_core_to_core_command));
-
- /* Update per-core command queue info. */
- q_info = &cd_region->cores[i].incoming_commands_queue;
- q_info->header.storage =
- app->core_cmd_queues_mem[i].device_addr;
- q_info->header.head_idx = 0;
- q_info->header.tail_idx = 0;
- q_info->header.element_size =
- sizeof(struct gxp_core_to_core_command);
- q_info->header.elements_count = cmd_queue_items;
- q_info->access_sem_id = semaphore_id++;
- q_info->posted_slots_sem_id = semaphore_id++;
- q_info->free_slots_sem_id = semaphore_id++;
-
- /* Allocate per-core response queue storage. */
- mem_size = resp_queue_items *
- sizeof(struct gxp_core_to_core_response);
- mem_alloc_allocate(
- app->mgr->allocator, &app->core_rsp_queues_mem[i],
- mem_size,
- __alignof__(struct gxp_core_to_core_response));
-
- /* Update per-core response queue info. */
- q_info = &cd_region->cores[i].incoming_responses_queue;
- q_info->header.storage =
- app->core_rsp_queues_mem[i].device_addr;
- q_info->header.head_idx = 0;
- q_info->header.tail_idx = 0;
- q_info->header.element_size =
- sizeof(struct gxp_core_to_core_response);
- q_info->header.elements_count = resp_queue_items;
- q_info->access_sem_id = semaphore_id++;
- q_info->posted_slots_sem_id = semaphore_id++;
- q_info->free_slots_sem_id = semaphore_id++;
- }
-
- return mem;
-}
-
-static struct fw_memory init_application(struct app_metadata *app)
-{
- struct gxp_application_descriptor *app_region;
- struct fw_memory mem;
- const int user_mem_size = DEFAULT_APP_USER_MEM_SIZE;
-
- /* App's system memory. */
- app->user_mem = init_app_user_memory(app, user_mem_size);
-
- /* App's doorbells region. */
- app->doorbells_mem = init_doorbells(app);
-
- /* App's sync barriers region. */
- app->sync_barriers_mem = init_sync_barriers(app);
-
- /* App's semaphores region. */
- app->semaphores_mem = init_app_semaphores(app);
-
- /* App's cores info and core-to-core queues. */
- app->cores_mem = init_app_cores(app);
-
- /* App's descriptor. */
- mem_alloc_allocate(app->mgr->allocator, &mem, sizeof(*app_region),
- __alignof__(struct gxp_application_descriptor));
- app_region = mem.host_addr;
- app_region->application_id = app->application_id;
- app_region->core_count = app->core_count;
- app_region->cores_mask = app->core_list;
- app_region->threads_count = DEFAULT_APP_THREAD_COUNT;
- app_region->tcm_memory_per_bank = DEFAULT_APP_TCM_PER_BANK;
- app_region->system_memory_size = user_mem_size;
- app_region->system_memory_addr = app->user_mem.device_addr;
- app_region->doorbells_dev_addr = app->doorbells_mem.device_addr;
- app_region->sync_barriers_dev_addr = app->sync_barriers_mem.device_addr;
- app_region->semaphores_dev_addr = app->semaphores_mem.device_addr;
- app_region->cores_info_dev_addr = app->cores_mem.device_addr;
-
- return mem;
-}
-
-static struct app_metadata *gxp_fw_data_create_app_legacy(struct gxp_dev *gxp,
- uint core_list)
-{
- struct gxp_fw_data_manager *mgr = gxp->data_mgr;
- struct app_metadata *app;
- void *err;
- int i;
-
- app = kzalloc(sizeof(*app), GFP_KERNEL);
- if (!app)
- return ERR_PTR(-ENOMEM);
-
- /* Create resource and memory allocations for new app */
- app->mgr = mgr;
- app->application_id = DEFAULT_APP_ID;
- app->core_count = hweight_long(core_list);
- app->core_list = core_list;
-
- /* User doorbells */
- app->user_doorbells_count = DEFAULT_APP_USER_DOORBELL_COUNT;
- app->user_doorbells =
- kcalloc(app->user_doorbells_count, sizeof(int), GFP_KERNEL);
- if (!app->user_doorbells) {
- err = ERR_PTR(-ENOMEM);
- goto err_user_doorbells;
- }
-
- for (i = 0; i < app->user_doorbells_count; i++) {
- range_alloc_get_any(mgr->doorbell_allocator,
- &app->user_doorbells[i]);
- }
-
- /* User sync barrier */
- app->user_barriers_count = DEFAULT_APP_USER_BARRIER_COUNT;
- app->user_barriers =
- kcalloc(app->user_barriers_count, sizeof(int), GFP_KERNEL);
- if (!app->user_barriers) {
- err = ERR_PTR(-ENOMEM);
- goto err_user_barriers;
- }
-
- for (i = 0; i < app->user_barriers_count; i++) {
- range_alloc_get_any(mgr->sync_barrier_allocator,
- &app->user_barriers[i]);
- }
-
- /* Application region. */
- app->app_mem = init_application(app);
- for (i = 0; i < GXP_NUM_CORES; i++) {
- if (core_list & BIT(i)) {
- mgr->system_desc->app_descriptor_dev_addr[i] =
- app->app_mem.device_addr;
- }
- }
-
- return app;
-
-err_user_barriers:
- for (i = 0; i < app->user_doorbells_count; i++)
- range_alloc_put(mgr->doorbell_allocator,
- app->user_doorbells[i]);
- kfree(app->user_doorbells);
-err_user_doorbells:
- kfree(app);
-
- return err;
-}
-
-static void gxp_fw_data_destroy_app_legacy(struct gxp_dev *gxp,
- struct app_metadata *app)
-{
- struct gxp_fw_data_manager *mgr = gxp->data_mgr;
- int i;
-
- for (i = 0; i < app->user_doorbells_count; i++)
- range_alloc_put(mgr->doorbell_allocator,
- app->user_doorbells[i]);
- kfree(app->user_doorbells);
-
- for (i = 0; i < app->user_barriers_count; i++)
- range_alloc_put(mgr->sync_barrier_allocator,
- app->user_barriers[i]);
- kfree(app->user_barriers);
-
- mem_alloc_free(mgr->allocator, &app->user_mem);
- mem_alloc_free(mgr->allocator, &app->doorbells_mem);
- mem_alloc_free(mgr->allocator, &app->sync_barriers_mem);
- mem_alloc_free(mgr->allocator, &app->semaphores_mem);
- mem_alloc_free(mgr->allocator, &app->cores_mem);
- for (i = 0; i < app->core_count; i++) {
- mem_alloc_free(mgr->allocator, &app->core_cmd_queues_mem[i]);
- mem_alloc_free(mgr->allocator, &app->core_rsp_queues_mem[i]);
- }
- mem_alloc_free(mgr->allocator, &app->app_mem);
-
- kfree(app);
-}
-
/*
* Here assumes sys_cfg contains gxp_system_descriptor_ro in the first page and
* gxp_system_descriptor_rw in the second page.
@@ -584,7 +50,7 @@ static void set_system_cfg_region(struct gxp_dev *gxp, void *sys_cfg)
struct gxp_system_descriptor_ro *des_ro = sys_cfg;
struct gxp_system_descriptor_rw *des_rw = sys_cfg + PAGE_SIZE;
struct gxp_core_telemetry_descriptor *descriptor =
- gxp->data_mgr->core_telemetry_mem.host_addr;
+ &gxp->data_mgr->core_telemetry_desc;
struct telemetry_descriptor_ro *tel_ro;
struct telemetry_descriptor_rw *tel_rw;
struct core_telemetry_descriptor *tel_des;
@@ -620,31 +86,23 @@ static void set_system_cfg_region(struct gxp_dev *gxp, void *sys_cfg)
gxp->data_mgr->sys_desc_rw = des_rw;
}
-static struct app_metadata *
-_gxp_fw_data_create_app(struct gxp_dev *gxp, struct gxp_virtual_device *vd)
+static void _gxp_fw_data_populate_vd_cfg(struct gxp_dev *gxp,
+ struct gxp_virtual_device *vd)
{
- struct app_metadata *app;
struct gxp_host_control_region *core_cfg;
struct gxp_job_descriptor job;
struct gxp_vd_descriptor *vd_desc;
int i;
- /*
- * If we are able to know where sys_cfg's virt is on init() then we
- * don't need this here, but to keep compatibility with
- * !use_per_vd_config, we keep gxp_fw_data_init() doing the
- * initialization of legacy mode, and have here copy the values to the
- * config region.
- */
- if (vd->vdid == 1)
- set_system_cfg_region(gxp, vd->sys_cfg.vaddr);
- app = kzalloc(sizeof(*app), GFP_KERNEL);
- if (!app)
- return ERR_PTR(-ENOMEM);
-
- if (!gxp_core_boot) {
+ if (!gxp_core_boot(gxp)) {
dev_info(gxp->dev, "Skip setting VD and core CFG");
- return app;
+ return;
+ }
+ if (!vd->vd_cfg.vaddr || !vd->core_cfg.vaddr) {
+ dev_warn(
+ gxp->dev,
+ "Missing VD and core CFG in image config, firmware is not bootable\n");
+ return;
}
/* Set up VD config region. */
vd_desc = vd->vd_cfg.vaddr;
@@ -673,213 +131,61 @@ _gxp_fw_data_create_app(struct gxp_dev *gxp, struct gxp_virtual_device *vd)
vd->core_cfg.size / GXP_NUM_CORES * i;
core_cfg->job_descriptor = job;
}
-
- return app;
}
-static void _gxp_fw_data_destroy_app(struct gxp_dev *gxp,
- struct app_metadata *app)
+static struct core_telemetry_descriptor *
+gxp_fw_data_get_core_telemetry_descriptor(struct gxp_dev *gxp, u8 type)
{
- kfree(app);
+ struct gxp_core_telemetry_descriptor *descriptor =
+ &gxp->data_mgr->core_telemetry_desc;
+
+ if (type == GXP_TELEMETRY_TYPE_LOGGING)
+ return descriptor->per_core_loggers;
+ else if (type == GXP_TELEMETRY_TYPE_TRACING)
+ return descriptor->per_core_tracers;
+ else
+ return ERR_PTR(-EINVAL);
}
int gxp_fw_data_init(struct gxp_dev *gxp)
{
struct gxp_fw_data_manager *mgr;
- int res;
- int i;
+ void *virt;
mgr = devm_kzalloc(gxp->dev, sizeof(*mgr), GFP_KERNEL);
if (!mgr)
return -ENOMEM;
- gxp->data_mgr = mgr;
- /*
- * TODO (b/200169232) Using memremap until devm_memremap is added to
- * the GKI ABI
- */
- mgr->fw_data_virt = memremap(gxp->fwdatabuf.paddr, gxp->fwdatabuf.size,
- MEMREMAP_WC);
+ virt = memremap(gxp->fwdatabuf.paddr, gxp->fwdatabuf.size, MEMREMAP_WC);
- if (IS_ERR_OR_NULL(mgr->fw_data_virt)) {
+ if (IS_ERR_OR_NULL(virt)) {
dev_err(gxp->dev, "Failed to map fw data region\n");
- res = -ENODEV;
- goto err;
- }
- gxp->fwdatabuf.vaddr = mgr->fw_data_virt;
-
- /* Instantiate the doorbells allocator with all doorbells */
- mgr->doorbell_allocator =
- range_alloc_create(/*start=*/0, DOORBELL_COUNT);
- if (IS_ERR(mgr->doorbell_allocator)) {
- dev_err(gxp->dev, "Failed to create doorbells allocator\n");
- res = PTR_ERR(mgr->doorbell_allocator);
- mgr->doorbell_allocator = NULL;
- goto err;
- }
-
- /* Instantiate the sync barriers allocator with all sync barriers */
- mgr->sync_barrier_allocator =
- range_alloc_create(/*start=*/0, SYNC_BARRIER_COUNT);
- if (IS_ERR(mgr->sync_barrier_allocator)) {
- dev_err(gxp->dev, "Failed to create sync barriers allocator\n");
- res = PTR_ERR(mgr->sync_barrier_allocator);
- mgr->sync_barrier_allocator = NULL;
- goto err;
- }
-
- /* Allocate doorbells */
-
- /* Pinned: Cores wakeup doorbell */
- for (i = 0; i < GXP_NUM_WAKEUP_DOORBELLS; i++) {
- mgr->core_wakeup_doorbells[i] = DOORBELL_ID_CORE_WAKEUP(i);
- res = range_alloc_get(mgr->doorbell_allocator,
- mgr->core_wakeup_doorbells[i]);
- if (res)
- goto err;
- }
-
- /* Semaphores operation doorbells */
- for (i = 0; i < GXP_NUM_CORES; i++) {
- range_alloc_get_any(mgr->doorbell_allocator,
- &mgr->semaphore_doorbells[i]);
- }
-
- /* Allocate sync barriers */
-
- /* Pinned: UART sync barrier */
- mgr->uart_sync_barrier = SYNC_BARRIER_ID_UART;
- mgr->uart_region_barrier = SYNC_BARRIER_ID_UART;
- res = range_alloc_get(mgr->sync_barrier_allocator,
- mgr->uart_sync_barrier);
- if (res)
- goto err;
-
- /* Doorbell regions for all apps */
- res = range_alloc_get_any(mgr->sync_barrier_allocator,
- &mgr->doorbell_regions_barrier);
- if (res)
- goto err;
-
- /* Sync barrier regions for all apps */
- res = range_alloc_get_any(mgr->sync_barrier_allocator,
- &mgr->sync_barrier_regions_barrier);
- if (res)
- goto err;
-
- /* Timer regions for all apps */
- res = range_alloc_get_any(mgr->sync_barrier_allocator,
- &mgr->timer_regions_barrier);
- if (res)
- goto err;
-
- /* Watchdog regions for all apps */
- res = range_alloc_get_any(mgr->sync_barrier_allocator,
- &mgr->watchdog_region_barrier);
- if (res)
- goto err;
-
- /* Semaphore regions for all apps */
- res = range_alloc_get_any(mgr->sync_barrier_allocator,
- &mgr->semaphores_regions_barrier);
- if (res)
- goto err;
-
- /* Shared firmware data memory region */
- mgr->allocator =
- mem_alloc_create(gxp, mgr->fw_data_virt, gxp->fwdatabuf.daddr,
- gxp->fwdatabuf.size);
- if (IS_ERR(mgr->allocator)) {
- dev_err(gxp->dev,
- "Failed to create the FW data memory allocator\n");
- res = PTR_ERR(mgr->allocator);
- mgr->allocator = NULL;
- goto err;
+ return -ENODEV;
}
+ gxp->fwdatabuf.vaddr = virt;
/* Populate the region with a pre-defined pattern. */
- memset(mgr->fw_data_virt, FW_DATA_DEBUG_PATTERN, gxp->fwdatabuf.size);
-
- /* Allocate the root system descriptor from the region */
- mem_alloc_allocate(mgr->allocator, &mgr->sys_desc_mem,
- sizeof(struct gxp_system_descriptor),
- __alignof__(struct gxp_system_descriptor));
- mgr->system_desc = mgr->sys_desc_mem.host_addr;
-
- /* Allocate the watchdog descriptor from the region */
- mgr->wdog_mem = init_watchdog(mgr);
- mgr->system_desc->watchdog_dev_addr = mgr->wdog_mem.device_addr;
-
- /* Allocate the descriptor for device-side core telemetry */
- mgr->core_telemetry_mem = init_core_telemetry(mgr);
- mgr->system_desc->core_telemetry_dev_addr =
- mgr->core_telemetry_mem.device_addr;
-
- /* Set the debug dump region parameters if available */
- mgr->debug_dump_mem = init_debug_dump(gxp);
- mgr->system_desc->debug_dump_dev_addr = mgr->debug_dump_mem.device_addr;
-
- return res;
-
-err:
- range_alloc_destroy(mgr->sync_barrier_allocator);
- range_alloc_destroy(mgr->doorbell_allocator);
- devm_kfree(gxp->dev, mgr);
- return res;
-}
-
-void *gxp_fw_data_create_app(struct gxp_dev *gxp, struct gxp_virtual_device *vd)
-{
- struct app_metadata *app;
-
- if (gxp_fw_data_use_per_vd_config(vd))
- app = _gxp_fw_data_create_app(gxp, vd);
- else
- app = gxp_fw_data_create_app_legacy(gxp, vd->core_list);
-
- if (IS_ERR(app))
- return app;
- app->vd = vd;
-
- return app;
-}
-
-void gxp_fw_data_destroy_app(struct gxp_dev *gxp, void *application)
-{
- struct app_metadata *app = application;
+ memset(virt, FW_DATA_DEBUG_PATTERN, gxp->fwdatabuf.size);
+ gxp->data_mgr = mgr;
- if (!app)
- return;
- if (gxp_fw_data_use_per_vd_config(app->vd))
- return _gxp_fw_data_destroy_app(gxp, app);
- return gxp_fw_data_destroy_app_legacy(gxp, app);
+ return 0;
}
void gxp_fw_data_destroy(struct gxp_dev *gxp)
{
struct gxp_fw_data_manager *mgr = gxp->data_mgr;
- if (!mgr)
- return;
-
- mem_alloc_free(mgr->allocator, &mgr->core_telemetry_mem);
- mem_alloc_free(mgr->allocator, &mgr->wdog_mem);
- mem_alloc_free(mgr->allocator, &mgr->sys_desc_mem);
- mem_alloc_destroy(mgr->allocator);
-
- range_alloc_destroy(mgr->sync_barrier_allocator);
- range_alloc_destroy(mgr->doorbell_allocator);
+ if (gxp->fwdatabuf.vaddr)
+ memunmap(gxp->fwdatabuf.vaddr);
- /* TODO (b/200169232) Remove this once we're using devm_memremap */
- if (mgr->fw_data_virt) {
- memunmap(mgr->fw_data_virt);
- mgr->fw_data_virt = NULL;
- }
+ devm_kfree(gxp->dev, mgr);
+ gxp->data_mgr = NULL;
+}
- if (gxp->data_mgr) {
- devm_kfree(gxp->dev, gxp->data_mgr);
- gxp->data_mgr = NULL;
- }
+void gxp_fw_data_populate_vd_cfg(struct gxp_dev *gxp, struct gxp_virtual_device *vd)
+{
+ if (gxp_fw_data_use_per_vd_config(vd))
+ _gxp_fw_data_populate_vd_cfg(gxp, vd);
}
int gxp_fw_data_set_core_telemetry_descriptors(struct gxp_dev *gxp, u8 type,
@@ -887,18 +193,13 @@ int gxp_fw_data_set_core_telemetry_descriptors(struct gxp_dev *gxp, u8 type,
struct gxp_coherent_buf *buffers,
u32 per_buffer_size)
{
- struct gxp_core_telemetry_descriptor *descriptor =
- gxp->data_mgr->core_telemetry_mem.host_addr;
struct core_telemetry_descriptor *core_descriptors;
uint core;
bool enable;
- if (type == GXP_TELEMETRY_TYPE_LOGGING)
- core_descriptors = descriptor->per_core_loggers;
- else if (type == GXP_TELEMETRY_TYPE_TRACING)
- core_descriptors = descriptor->per_core_tracers;
- else
- return -EINVAL;
+ core_descriptors = gxp_fw_data_get_core_telemetry_descriptor(gxp, type);
+ if (IS_ERR(core_descriptors))
+ return PTR_ERR(core_descriptors);
enable = (host_status & GXP_CORE_TELEMETRY_HOST_STATUS_ENABLED);
@@ -927,27 +228,13 @@ int gxp_fw_data_set_core_telemetry_descriptors(struct gxp_dev *gxp, u8 type,
return 0;
}
-static u32
-gxp_fw_data_get_core_telemetry_device_status_legacy(struct gxp_dev *gxp,
- uint core, u8 type)
+u32 gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp, uint core,
+ u8 type)
{
- struct gxp_core_telemetry_descriptor *descriptor =
- gxp->data_mgr->core_telemetry_mem.host_addr;
+ struct gxp_system_descriptor_rw *des_rw = gxp->data_mgr->sys_desc_rw;
- switch (type) {
- case GXP_TELEMETRY_TYPE_LOGGING:
- return descriptor->per_core_loggers[core].device_status;
- case GXP_TELEMETRY_TYPE_TRACING:
- return descriptor->per_core_tracers[core].device_status;
- default:
+ if (core >= GXP_NUM_CORES)
return 0;
- }
-}
-
-static u32 _gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp,
- uint core, u8 type)
-{
- struct gxp_system_descriptor_rw *des_rw = gxp->data_mgr->sys_desc_rw;
switch (type) {
case GXP_TELEMETRY_TYPE_LOGGING:
@@ -961,18 +248,32 @@ static u32 _gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp,
}
}
-u32 gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp, uint core,
- u8 type)
+struct gxp_mapped_resource gxp_fw_data_resource(struct gxp_dev *gxp)
{
- if (core >= GXP_NUM_CORES)
- return 0;
+ /*
+ * For direct mode, the config regions are programmed by host (us); for
+ * MCU mode, the config regions are programmed by MCU.
+ */
+ if (gxp_is_direct_mode(gxp)) {
+ struct gxp_mapped_resource tmp = gxp->fwdatabuf;
- if (gxp->firmware_mgr->img_cfg.config_version >=
- FW_DATA_PROTOCOL_PER_VD_CONFIG) {
- return _gxp_fw_data_get_core_telemetry_device_status(gxp, core,
- type);
+ /* Leave the first piece be used for gxp_fw_data_init() */
+ tmp.vaddr += tmp.size / 2;
+ tmp.paddr += tmp.size / 2;
+ return tmp;
} else {
- return gxp_fw_data_get_core_telemetry_device_status_legacy(
- gxp, core, type);
+ return gxp->shared_buf;
}
}
+
+void *gxp_fw_data_system_cfg(struct gxp_dev *gxp)
+{
+ /* Use the end of the shared region for system cfg. */
+ return gxp_fw_data_resource(gxp).vaddr + GXP_SHARED_BUFFER_SIZE -
+ GXP_FW_DATA_SYSCFG_SIZE;
+}
+
+void gxp_fw_data_populate_system_config(struct gxp_dev *gxp)
+{
+ set_system_cfg_region(gxp, gxp_fw_data_system_cfg(gxp));
+}