diff --git a/userspace/units/falcon/falcon_tests/falcon.c b/userspace/units/falcon/falcon_tests/falcon.c index ca45f5bd0..8e68a2f94 100644 --- a/userspace/units/falcon/falcon_tests/falcon.c +++ b/userspace/units/falcon/falcon_tests/falcon.c @@ -33,6 +33,8 @@ #include "../falcon_utf.h" +struct utf_falcon *utf_falcons[FALCON_ID_END]; + static struct nvgpu_falcon *pmu_flcn; static struct nvgpu_falcon *gpccs_flcn; static struct nvgpu_falcon *uninit_flcn; @@ -45,6 +47,71 @@ static u32 *rand_test_data; #define RAND_DATA_SIZE (SZ_4K) +static struct utf_falcon *get_utf_falcon_from_addr(struct gk20a *g, u32 addr) +{ + struct utf_falcon *flcn = NULL; + u32 flcn_base; + u32 i; + + for (i = 0; i < FALCON_ID_END; i++) { + if (utf_falcons[i] == NULL || utf_falcons[i]->flcn == NULL) { + continue; + } + + flcn_base = utf_falcons[i]->flcn->flcn_base; + if ((addr >= flcn_base) && + (addr < (flcn_base + UTF_FALCON_MAX_REG_OFFSET))) { + flcn = utf_falcons[i]; + break; + } + } + + return flcn; +} + +static void writel_access_reg_fn(struct gk20a *g, + struct nvgpu_reg_access *access) +{ + struct utf_falcon *flcn = NULL; + + flcn = get_utf_falcon_from_addr(g, access->addr); + if (flcn != NULL) { + nvgpu_utf_falcon_writel_access_reg_fn(g, flcn, access); + } else { + nvgpu_posix_io_writel_reg_space(g, access->addr, access->value); + } + nvgpu_posix_io_record_access(g, access); +} + +static void readl_access_reg_fn(struct gk20a *g, + struct nvgpu_reg_access *access) +{ + struct utf_falcon *flcn = NULL; + + flcn = get_utf_falcon_from_addr(g, access->addr); + if (flcn != NULL) { + nvgpu_utf_falcon_readl_access_reg_fn(g, flcn, access); + } else { + access->value = nvgpu_posix_io_readl_reg_space(g, access->addr); + } +} + +static struct nvgpu_posix_io_callbacks utf_falcon_reg_callbacks = { + .writel = writel_access_reg_fn, + .writel_check = writel_access_reg_fn, + .bar1_writel = writel_access_reg_fn, + .usermode_writel = writel_access_reg_fn, + + .__readl = readl_access_reg_fn, + .readl = readl_access_reg_fn, + .bar1_readl = readl_access_reg_fn, +}; + +static void utf_falcon_register_io(struct gk20a *g) +{ + nvgpu_posix_register_io(g, &utf_falcon_reg_callbacks); +} + static void init_rand_buffer(void) { u32 i; @@ -64,7 +131,7 @@ static int init_falcon_test_env(struct unit_module *m, struct gk20a *g) int err = 0; nvgpu_posix_io_init_reg_space(g); - nvgpu_utf_falcon_register_io(g); + utf_falcon_register_io(g); /* * Fuse register fuse_opt_priv_sec_en_r() is read during init_hal hence @@ -87,14 +154,15 @@ static int init_falcon_test_env(struct unit_module *m, struct gk20a *g) } /* Initialize utf & nvgpu falcon for test usage */ - err = nvgpu_utf_falcon_init(m, g, FALCON_ID_PMU); - if (err) { - return err; + utf_falcons[FALCON_ID_PMU] = nvgpu_utf_falcon_init(m, g, FALCON_ID_PMU); + if (utf_falcons[FALCON_ID_PMU] == NULL) { + return -ENODEV; } - err = nvgpu_utf_falcon_init(m, g, FALCON_ID_GPCCS); - if (err) { - return err; + utf_falcons[FALCON_ID_GPCCS] = + nvgpu_utf_falcon_init(m, g, FALCON_ID_GPCCS); + if (utf_falcons[FALCON_ID_GPCCS] == NULL) { + return -ENODEV; } /* Set falcons for test usage */ @@ -120,7 +188,8 @@ static int free_falcon_test_env(struct unit_module *m, struct gk20a *g, } nvgpu_kfree(g, rand_test_data); - nvgpu_utf_falcon_free(g, FALCON_ID_PMU); + nvgpu_utf_falcon_free(g, utf_falcons[FALCON_ID_GPCCS]); + nvgpu_utf_falcon_free(g, utf_falcons[FALCON_ID_PMU]); return UNIT_SUCCESS; } diff --git a/userspace/units/falcon/falcon_utf.c b/userspace/units/falcon/falcon_utf.c index a0ed883b0..3fcd90e1b 100644 --- a/userspace/units/falcon/falcon_utf.c +++ b/userspace/units/falcon/falcon_utf.c @@ -29,56 +29,9 @@ #include "falcon_utf.h" -struct utf_falcon utf_falcons[FALCON_ID_END]; - -static struct utf_falcon *get_utf_falcon_from_id(struct gk20a *g, u32 falcon_id) -{ - struct utf_falcon *flcn = NULL; - - switch (falcon_id) { - case FALCON_ID_PMU: - case FALCON_ID_FECS: - case FALCON_ID_GPCCS: -#ifdef CONFIG_NVGPU_DGPU - case FALCON_ID_GSPLITE: - case FALCON_ID_NVDEC: - case FALCON_ID_SEC2: - case FALCON_ID_MINION: -#endif - flcn = &utf_falcons[falcon_id]; - break; - default: - break; - } - - return flcn; -} - -static struct utf_falcon *get_utf_falcon_from_addr(struct gk20a *g, u32 addr) -{ - struct utf_falcon *flcn = NULL; - u32 flcn_base; - u32 i; - - for (i = 0; i < FALCON_ID_END; i++) { - if (utf_falcons[i].flcn == NULL) { - continue; - } - - flcn_base = utf_falcons[i].flcn->flcn_base; - if ((addr >= flcn_base) && - (addr < (flcn_base + UTF_FALCON_MAX_REG_OFFSET))) { - flcn = get_utf_falcon_from_id(g, i); - break; - } - } - - return flcn; -} - -static void falcon_writel_access_reg_fn(struct gk20a *g, - struct utf_falcon *flcn, - struct nvgpu_reg_access *access) +void nvgpu_utf_falcon_writel_access_reg_fn(struct gk20a *g, + struct utf_falcon *flcn, + struct nvgpu_reg_access *access) { u32 addr_mask = falcon_falcon_dmemc_offs_m() | falcon_falcon_dmemc_blk_m(); @@ -123,9 +76,9 @@ static void falcon_writel_access_reg_fn(struct gk20a *g, nvgpu_posix_io_writel_reg_space(g, access->addr, access->value); } -static void falcon_readl_access_reg_fn(struct gk20a *g, - struct utf_falcon *flcn, - struct nvgpu_reg_access *access) +void nvgpu_utf_falcon_readl_access_reg_fn(struct gk20a *g, + struct utf_falcon *flcn, + struct nvgpu_reg_access *access) { u32 addr_mask = falcon_falcon_dmemc_offs_m() | falcon_falcon_dmemc_blk_m(); @@ -176,72 +129,27 @@ static void falcon_readl_access_reg_fn(struct gk20a *g, } } -static void writel_access_reg_fn(struct gk20a *g, - struct nvgpu_reg_access *access) -{ - struct utf_falcon *flcn = NULL; - - flcn = get_utf_falcon_from_addr(g, access->addr); - if (flcn != NULL) { - falcon_writel_access_reg_fn(g, flcn, access); - } else { - nvgpu_posix_io_writel_reg_space(g, access->addr, access->value); - } - nvgpu_posix_io_record_access(g, access); -} - -static void readl_access_reg_fn(struct gk20a *g, - struct nvgpu_reg_access *access) -{ - struct utf_falcon *flcn = NULL; - - flcn = get_utf_falcon_from_addr(g, access->addr); - if (flcn != NULL) { - falcon_readl_access_reg_fn(g, flcn, access); - } else { - access->value = nvgpu_posix_io_readl_reg_space(g, access->addr); - } -} - -static struct nvgpu_posix_io_callbacks utf_falcon_reg_callbacks = { - .writel = writel_access_reg_fn, - .writel_check = writel_access_reg_fn, - .bar1_writel = writel_access_reg_fn, - .usermode_writel = writel_access_reg_fn, - - .__readl = readl_access_reg_fn, - .readl = readl_access_reg_fn, - .bar1_readl = readl_access_reg_fn, -}; - -void nvgpu_utf_falcon_register_io(struct gk20a *g) -{ - nvgpu_posix_register_io(g, &utf_falcon_reg_callbacks); -} - -int nvgpu_utf_falcon_init(struct unit_module *m, struct gk20a *g, u32 flcn_id) +struct utf_falcon *nvgpu_utf_falcon_init(struct unit_module *m, + struct gk20a *g, u32 flcn_id) { struct utf_falcon *utf_flcn; struct nvgpu_falcon *flcn; u32 flcn_size; u32 flcn_base; u32 hwcfg_r, hwcfg1_r, ports; - int err = 0; - if (utf_falcons[flcn_id].flcn != NULL) { - unit_err(m, "Falcon already initialized!\n"); - return -EINVAL; - } - - err = nvgpu_falcon_sw_init(g, flcn_id); - if (err != 0) { + if (nvgpu_falcon_sw_init(g, flcn_id) != 0) { unit_err(m, "nvgpu Falcon init failed!\n"); - return err; + return NULL; } flcn = nvgpu_falcon_get_instance(g, flcn_id); - utf_flcn = &utf_falcons[flcn_id]; + utf_flcn = (struct utf_falcon *) malloc(sizeof(struct utf_falcon)); + if (!utf_flcn) { + return NULL; + } + utf_flcn->flcn = flcn; flcn_base = flcn->flcn_base; @@ -249,8 +157,7 @@ int nvgpu_utf_falcon_init(struct unit_module *m, struct gk20a *g, u32 flcn_id) flcn_base, UTF_FALCON_MAX_REG_OFFSET) != 0) { unit_err(m, "Falcon add reg space failed!\n"); - nvgpu_falcon_sw_free(g, flcn_id); - return -ENOMEM; + goto out; } /* @@ -269,52 +176,46 @@ int nvgpu_utf_falcon_init(struct unit_module *m, struct gk20a *g, u32 flcn_id) utf_flcn->imem = (u32 *) nvgpu_kzalloc(g, UTF_FALCON_IMEM_DMEM_SIZE); if (utf_flcn->imem == NULL) { - err = -ENOMEM; unit_err(m, "Falcon imem alloc failed!\n"); - goto out; + goto out_reg_space; } utf_flcn->dmem = (u32 *) nvgpu_kzalloc(g, UTF_FALCON_IMEM_DMEM_SIZE); if (utf_flcn->dmem == NULL) { - err = -ENOMEM; unit_err(m, "Falcon dmem alloc failed!\n"); - goto clean_imem; + goto free_imem; } - return 0; + return utf_flcn; -clean_imem: +free_imem: nvgpu_kfree(g, utf_flcn->imem); -out: +out_reg_space: nvgpu_posix_io_delete_reg_space(g, flcn_base); +out: nvgpu_falcon_sw_free(g, flcn_id); + free(utf_flcn); - return err; + return NULL; } -void nvgpu_utf_falcon_free(struct gk20a *g, u32 flcn_id) +void nvgpu_utf_falcon_free(struct gk20a *g, struct utf_falcon *utf_flcn) { - struct utf_falcon *utf_flcn; - - utf_flcn = &utf_falcons[flcn_id]; - - if (utf_flcn->flcn == NULL) + if (utf_flcn == NULL || utf_flcn->flcn == NULL) return; nvgpu_kfree(g, utf_flcn->dmem); nvgpu_kfree(g, utf_flcn->imem); nvgpu_posix_io_delete_reg_space(g, utf_flcn->flcn->flcn_base); - nvgpu_falcon_sw_free(g, flcn_id); - utf_flcn->flcn = NULL; + nvgpu_falcon_sw_free(g, utf_flcn->flcn->flcn_id); + free(utf_flcn); } -void nvgpu_utf_falcon_set_dmactl(struct gk20a *g, u32 flcn_id, u32 reg_data) +void nvgpu_utf_falcon_set_dmactl(struct gk20a *g, struct utf_falcon *utf_flcn, + u32 reg_data) { - struct utf_falcon *utf_flcn; u32 flcn_base; - utf_flcn = &utf_falcons[flcn_id]; - flcn_base = utf_flcn->flcn->flcn_base; nvgpu_posix_io_writel_reg_space(g, diff --git a/userspace/units/falcon/falcon_utf.h b/userspace/units/falcon/falcon_utf.h index 0b2721d58..3ca6cb73e 100644 --- a/userspace/units/falcon/falcon_utf.h +++ b/userspace/units/falcon/falcon_utf.h @@ -38,9 +38,16 @@ struct utf_falcon { u32 *dmem; }; -void nvgpu_utf_falcon_register_io(struct gk20a *g); -int nvgpu_utf_falcon_init(struct unit_module *m, struct gk20a *g, u32 flcn_id); -void nvgpu_utf_falcon_set_dmactl(struct gk20a *g, u32 flcn_id, u32 reg_data); -void nvgpu_utf_falcon_free(struct gk20a *g, u32 flcn_id); +void nvgpu_utf_falcon_writel_access_reg_fn(struct gk20a *g, + struct utf_falcon *flcn, + struct nvgpu_reg_access *access); +void nvgpu_utf_falcon_readl_access_reg_fn(struct gk20a *g, + struct utf_falcon *flcn, + struct nvgpu_reg_access *access); +struct utf_falcon *nvgpu_utf_falcon_init(struct unit_module *m, + struct gk20a *g, u32 flcn_id); +void nvgpu_utf_falcon_free(struct gk20a *g, struct utf_falcon *utf_flcn); +void nvgpu_utf_falcon_set_dmactl(struct gk20a *g, struct utf_falcon *utf_flcn, + u32 reg_data); #endif diff --git a/userspace/units/falcon/libfalcon_utf.export b/userspace/units/falcon/libfalcon_utf.export index 53554f557..50a81d377 100644 --- a/userspace/units/falcon/libfalcon_utf.export +++ b/userspace/units/falcon/libfalcon_utf.export @@ -22,5 +22,6 @@ nvgpu_utf_falcon_free nvgpu_utf_falcon_init -nvgpu_utf_falcon_register_io +nvgpu_utf_falcon_readl_access_reg_fn nvgpu_utf_falcon_set_dmactl +nvgpu_utf_falcon_writel_access_reg_fn