diff options
author | Aurora zuma automerger <aurora-zuma-automerger@google.com> | 2023-03-28 13:25:52 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-04-10 11:04:23 -0700 |
commit | 0f9718887f9f52c056812dc6e21a6451cc8f4b12 (patch) | |
tree | 8175e4e5f4a198d39c9a03ac20fab937c73ade02 | |
parent | 2ddcce971c7d6a92830220df66b8b70abb621392 (diff) | |
download | zuma-0f9718887f9f52c056812dc6e21a6451cc8f4b12.tar.gz |
gxp: [Copybara Auto Merge] Merge branch 'zuma' into 'android14-gs-pixel-5.15'
gxp: Fix for debug dump in direct mode
Bug: 275477663
gxp: release awaiter while cleaning up dest_queue
Bug: 275650894
gxp: map first page of system config region as RO
Bug: 273923526
gxp: twice the time limit of LPM transition
Bug: 270655971
gxp: notify ACPM Tj status for AUR on/off
Bug: 270589821
gcip: KCI accept out-of-order responses
Bug: 274574929
GCIP_MAIN_REV_ID: 10df044567ceb004b88e7889568367a8614abc71
gcip: Define new gcip_kci_code for setting device properties
Bug: 273578844
GCIP_HEADERS_REV_ID: 571259837fd27887e9628169ed6d351f36706fcd
gxp: bump version 1.13
gxp: Pass down system properties to firmware
Bug: 273578844 (repeat)
gxp: Use scmversion instead of GIT_REPO_TAG
Bug: 274893782
gxp: hardcode git command path
Bug: 274893782 (repeat)
gxp: remove unnecessary log of skipping config
gxp: fix gem5 compatibility with gcip-iommu
gxp: Clarify usage of dma_sync_sg_for_*
GitOrigin-RevId: 84b983638068246128beb77ec3200253e0d00ccc
Change-Id: I560b82e7f2e26e055e57829f963d581b02503543
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | callisto-platform.c | 2 | ||||
-rw-r--r-- | gcip-kernel-driver/drivers/gcip/gcip-kci.c | 2 | ||||
-rw-r--r-- | gcip-kernel-driver/include/gcip/gcip-kci.h | 1 | ||||
-rw-r--r-- | gxp-common-platform.c | 18 | ||||
-rw-r--r-- | gxp-debug-dump.c | 27 | ||||
-rw-r--r-- | gxp-dma-iommu.c | 16 | ||||
-rw-r--r-- | gxp-domain-pool.c | 4 | ||||
-rw-r--r-- | gxp-firmware-data.c | 4 | ||||
-rw-r--r-- | gxp-internal.h | 11 | ||||
-rw-r--r-- | gxp-kci.c | 34 | ||||
-rw-r--r-- | gxp-kci.h | 7 | ||||
-rw-r--r-- | gxp-lpm.c | 2 | ||||
-rw-r--r-- | gxp-mcu-firmware.c | 7 | ||||
-rw-r--r-- | gxp-mcu-fs.c | 23 | ||||
-rw-r--r-- | gxp-pm.c | 29 | ||||
-rw-r--r-- | gxp-uci.c | 20 | ||||
-rw-r--r-- | gxp-vd.c | 59 | ||||
-rw-r--r-- | gxp-vd.h | 16 | ||||
-rw-r--r-- | gxp.h | 19 |
20 files changed, 272 insertions, 39 deletions
@@ -68,11 +68,11 @@ M ?= $(shell pwd) # Obtain the current git commit hash for logging on probe GIT_PATH=$(shell cd $(KERNEL_SRC); readlink -e $(M)) -ifeq ($(shell git --git-dir=$(GIT_PATH)/.git rev-parse --is-inside-work-tree),true) - GIT_REPO_STATE=$(shell (git --git-dir=$(GIT_PATH)/.git --work-tree=$(GIT_PATH) status --porcelain | grep -q .) && echo -dirty) - ccflags-y += -DGIT_REPO_TAG=\"$(shell git --git-dir=$(GIT_PATH)/.git rev-parse --short HEAD)$(GIT_REPO_STATE)\" -else - ccflags-y += -DGIT_REPO_TAG=\"Not\ a\ git\ repository\" +GIT_BIN=/usr/bin/git +GIT=$(GIT_BIN) -C $(GIT_PATH) +ifeq ($(shell $(GIT) rev-parse --is-inside-work-tree),true) + GIT_REPO_STATE=$(shell ($(GIT) --work-tree=$(GIT_PATH) status --porcelain | grep -q .) && echo -dirty) + ccflags-y += -DGIT_REPO_TAG=\"$(shell $(GIT) rev-parse --short HEAD)$(GIT_REPO_STATE)\" endif # If building via make directly, specify target platform by adding diff --git a/callisto-platform.c b/callisto-platform.c index 838f066..a316be2 100644 --- a/callisto-platform.c +++ b/callisto-platform.c @@ -135,6 +135,8 @@ static void __exit gxp_platform_exit(void) MODULE_DESCRIPTION("Google GXP platform driver"); MODULE_LICENSE("GPL v2"); +#ifdef GIT_REPO_TAG MODULE_INFO(gitinfo, GIT_REPO_TAG); +#endif module_init(gxp_platform_init); module_exit(gxp_platform_exit); diff --git a/gcip-kernel-driver/drivers/gcip/gcip-kci.c b/gcip-kernel-driver/drivers/gcip/gcip-kci.c index c3da416..58852d5 100644 --- a/gcip-kernel-driver/drivers/gcip/gcip-kci.c +++ b/gcip-kernel-driver/drivers/gcip/gcip-kci.c @@ -477,7 +477,7 @@ int gcip_kci_init(struct gcip_kci *kci, const struct gcip_kci_args *args) mailbox_args.timeout = args->timeout; mailbox_args.ops = &gcip_mailbox_ops; mailbox_args.data = kci; - mailbox_args.ignore_seq_order = false; + mailbox_args.ignore_seq_order = true; ret = gcip_mailbox_init(&kci->mailbox, &mailbox_args); if (ret) diff --git a/gcip-kernel-driver/include/gcip/gcip-kci.h b/gcip-kernel-driver/include/gcip/gcip-kci.h index 2aa721b..51dd803 100644 --- a/gcip-kernel-driver/include/gcip/gcip-kci.h +++ b/gcip-kernel-driver/include/gcip/gcip-kci.h @@ -103,6 +103,7 @@ enum gcip_kci_code { GCIP_KCI_CODE_FIRMWARE_TRACING_LEVEL = 19, GCIP_KCI_CODE_THERMAL_CONTROL = 20, GCIP_KCI_CODE_GET_USAGE_V2 = 21, + GCIP_KCI_CODE_SET_DEVICE_PROPERTIES = 22, GCIP_KCI_CODE_RKCI_ACK = 256, }; diff --git a/gxp-common-platform.c b/gxp-common-platform.c index 37c1654..7116553 100644 --- a/gxp-common-platform.c +++ b/gxp-common-platform.c @@ -1419,6 +1419,17 @@ out: return ret; } +static inline const char *get_driver_commit(void) +{ +#if IS_ENABLED(CONFIG_MODULE_SCMVERSION) + return THIS_MODULE->scmversion; +#elif defined(GIT_REPO_TAG) + return GIT_REPO_TAG; +#else + return "Unknown"; +#endif +} + static int gxp_get_interface_version(struct gxp_client *client, struct gxp_interface_version_ioctl __user *argp) @@ -1431,12 +1442,12 @@ gxp_get_interface_version(struct gxp_client *client, memset(ibuf.version_build, 0, GXP_INTERFACE_VERSION_BUILD_BUFFER_SIZE); ret = snprintf(ibuf.version_build, GXP_INTERFACE_VERSION_BUILD_BUFFER_SIZE - 1, - GIT_REPO_TAG); + get_driver_commit()); if (ret < 0 || ret >= GXP_INTERFACE_VERSION_BUILD_BUFFER_SIZE) { dev_warn( client->gxp->dev, - "Buffer size insufficient to hold GIT_REPO_TAG (size=%d)\n", + "Buffer size insufficient to hold git build info (size=%d)\n", ret); } @@ -1988,7 +1999,7 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de int ret; u64 prop; - dev_notice(dev, "Probing gxp driver with commit %s\n", GIT_REPO_TAG); + dev_notice(dev, "Probing gxp driver with commit %s\n", get_driver_commit()); platform_set_drvdata(pdev, gxp); gxp->dev = dev; @@ -2043,6 +2054,7 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de mutex_init(&gxp->pin_user_pages_lock); mutex_init(&gxp->secure_vd_lock); + mutex_init(&gxp->device_prop.lock); gxp->domain_pool = kmalloc(sizeof(*gxp->domain_pool), GFP_KERNEL); if (!gxp->domain_pool) { diff --git a/gxp-debug-dump.c b/gxp-debug-dump.c index 148fa25..ad9b49c 100644 --- a/gxp-debug-dump.c +++ b/gxp-debug-dump.c @@ -471,6 +471,7 @@ out: * @gxp: The GXP device. * @vd: vd of the crashed client. * @core_id: physical core_id of crashed core. + * @virt_core_id: virtual core_id of crashed core. * @seg_idx: Pointer to a index that is keeping track of * gxp->debug_dump_mgr->segs[] array. * @@ -484,12 +485,13 @@ out: */ static int gxp_map_fw_rw_section(struct gxp_dev *gxp, struct gxp_virtual_device *vd, - uint32_t core_id, int *seg_idx) + uint32_t core_id, uint32_t virt_core_id, + int *seg_idx) { size_t idx; struct sg_table *sgt; struct gxp_debug_dump_manager *mgr = gxp->debug_dump_mgr; - dma_addr_t fw_rw_section_daddr = CORE_FIRMWARE_RW_ADDR(core_id); + dma_addr_t fw_rw_section_daddr = CORE_FIRMWARE_RW_ADDR(virt_core_id); const size_t n_reg = ARRAY_SIZE(vd->ns_regions); if (!gxp_fw_data_use_per_vd_config(vd)) { @@ -569,6 +571,7 @@ static int gxp_handle_debug_dump(struct gxp_dev *gxp, struct gxp_core_dump_header *core_dump_header = &core_dump->core_dump_header[core_id]; struct gxp_core_header *core_header = &core_dump_header->core_header; + int virt_core; int ret = 0; #if HAS_COREDUMP struct gxp_common_dump *common_dump = mgr->common_dump; @@ -636,13 +639,27 @@ static int gxp_handle_debug_dump(struct gxp_dev *gxp, ret = -EFAULT; goto out_efault; } + + if (gxp_is_direct_mode(gxp)) { + virt_core = gxp_vd_phys_core_to_virt_core(vd, core_id); + if (virt_core < 0) { + dev_err(gxp->dev, + "No virtual core for physical core %u.\n", + core_id); + ret = -EINVAL; + goto out; + } + } else { + virt_core = core_id; + } + /* fw ro section */ - mgr->segs[core_id][seg_idx].addr = gxp->fwbufs[core_id].vaddr; - mgr->segs[core_id][seg_idx].size = gxp->fwbufs[core_id].size; + mgr->segs[core_id][seg_idx].addr = gxp->fwbufs[virt_core].vaddr; + mgr->segs[core_id][seg_idx].size = gxp->fwbufs[virt_core].size; seg_idx++; /* fw rw section */ - ret = gxp_map_fw_rw_section(gxp, vd, core_id, &seg_idx); + ret = gxp_map_fw_rw_section(gxp, vd, core_id, virt_core, &seg_idx); if (ret) goto out; diff --git a/gxp-dma-iommu.c b/gxp-dma-iommu.c index d78bc1a..0cedfb8 100644 --- a/gxp-dma-iommu.c +++ b/gxp-dma-iommu.c @@ -701,14 +701,26 @@ void gxp_dma_unmap_iova_sgt(struct gxp_dev *gxp, void gxp_dma_sync_sg_for_cpu(struct gxp_dev *gxp, struct scatterlist *sg, int nents, enum dma_data_direction direction) { - /* Syncing is not domain specific. Just call through to DMA API */ + /* + * Syncing is not domain specific. Just call through to DMA API. + * + * This works even for buffers not mapped via the DMA API, since the + * dma-iommu implementation syncs buffers by their physical address + * ranges, taken from the scatterlist, without using the IOVA. + */ dma_sync_sg_for_cpu(gxp->dev, sg, nents, direction); } void gxp_dma_sync_sg_for_device(struct gxp_dev *gxp, struct scatterlist *sg, int nents, enum dma_data_direction direction) { - /* Syncing is not domain specific. Just call through to DMA API */ + /* + * Syncing is not domain specific. Just call through to DMA API. + * + * This works even for buffers not mapped via the DMA API, since the + * dma-iommu implementation syncs buffers by their physical address + * ranges, taken from the scatterlist, without using the IOVA. + */ dma_sync_sg_for_device(gxp->dev, sg, nents, direction); } diff --git a/gxp-domain-pool.c b/gxp-domain-pool.c index 2f6167b..44a976a 100644 --- a/gxp-domain-pool.c +++ b/gxp-domain-pool.c @@ -43,7 +43,7 @@ int gxp_domain_pool_init(struct gxp_dev *gxp, #if IS_ENABLED(CONFIG_GXP_GEM5) for (i = 0; i < size; i++) { - struct iommu_domain *domain = pool->array[i]; + struct iommu_domain *domain = pool->domain_pool.array[i]; /* * Gem5 uses arm-smmu-v3 which requires domain finalization to do iommu map. Calling @@ -55,7 +55,7 @@ int gxp_domain_pool_init(struct gxp_dev *gxp, dev_err(gxp->dev, "Failed to attach device to iommu domain %d of %u, ret=%d\n", i + 1, size, ret); - gxp_domain_pool_destroy(pool); + gcip_iommu_domain_pool_destroy(pool); return ret; } diff --git a/gxp-firmware-data.c b/gxp-firmware-data.c index 841e80e..a98a183 100644 --- a/gxp-firmware-data.c +++ b/gxp-firmware-data.c @@ -94,10 +94,8 @@ static void _gxp_fw_data_populate_vd_cfg(struct gxp_dev *gxp, struct gxp_vd_descriptor *vd_desc; int i; - if (!gxp_core_boot(gxp)) { - dev_info(gxp->dev, "Skip setting VD and core CFG"); + if (!gxp_core_boot(gxp)) return; - } if (!vd->vd_cfg.vaddr || !vd->core_cfg.vaddr) { dev_warn( gxp->dev, diff --git a/gxp-internal.h b/gxp-internal.h index ba4cf7b..dcbc13e 100644 --- a/gxp-internal.h +++ b/gxp-internal.h @@ -26,6 +26,7 @@ #include <gcip/gcip-thermal.h> #include "gxp-config.h" +#include "gxp.h" #define IS_GXP_TEST IS_ENABLED(CONFIG_GXP_TEST) @@ -52,6 +53,13 @@ struct gxp_mapped_resource { resource_size_t size; /* size in bytes */ }; +/* device properties */ +struct gxp_dev_prop { + struct mutex lock; /* protects initialized and opaque */ + bool initialized; + u8 opaque[GXP_DEV_PROP_SIZE]; +}; + /* Structure to hold TPU device info */ struct gxp_tpu_dev { struct device *dev; @@ -145,6 +153,9 @@ struct gxp_dev { /* To manage DMA fences. */ struct gcip_dma_fence_manager *gfence_mgr; + /* To save device properties */ + struct gxp_dev_prop device_prop; + /* callbacks for chip-dependent implementations */ /* @@ -665,3 +665,37 @@ void gxp_kci_resp_rkci_ack(struct gxp_kci *gkci, dev_err(gxp->dev, "failed to send rkci resp %llu (%d)", rkci_cmd->seq, ret); } + +int gxp_kci_set_device_properties(struct gxp_kci *gkci, + struct gxp_dev_prop *dev_prop) +{ + struct gcip_kci_command_element cmd = { + .code = GCIP_KCI_CODE_SET_DEVICE_PROPERTIES, + }; + struct gxp_mapped_resource buf; + int ret = 0; + + if (!gkci || !gkci->mbx) + return -ENODEV; + + mutex_lock(&dev_prop->lock); + if (!dev_prop->initialized) + goto out; + + if (gxp_mcu_mem_alloc_data(gkci->mcu, &buf, sizeof(dev_prop->opaque))) { + ret = -ENOMEM; + goto out; + } + + memcpy(buf.vaddr, &dev_prop->opaque, sizeof(dev_prop->opaque)); + + cmd.dma.address = buf.daddr; + cmd.dma.size = sizeof(dev_prop->opaque); + + ret = gxp_kci_send_cmd(gkci->mbx, &cmd); + gxp_mcu_mem_free_data(gkci->mcu, &buf); + +out: + mutex_unlock(&dev_prop->lock); + return ret; +} @@ -233,4 +233,11 @@ int gxp_kci_link_unlink_offload_vmbox( void gxp_kci_resp_rkci_ack(struct gxp_kci *gkci, struct gcip_kci_response_element *rkci_cmd); +/* + * Send device properties to firmware. + * The device_prop KCI will be sent only when it is initialized. + */ +int gxp_kci_set_device_properties(struct gxp_kci *gkci, + struct gxp_dev_prop *device_prop); + #endif /* __GXP_KCI_H__ */ @@ -26,7 +26,7 @@ PSM_CURR_STATE_MASK; \ if (condition) \ break; \ - udelay(1 * GXP_TIME_DELAY_FACTOR); \ + udelay(2 * GXP_TIME_DELAY_FACTOR); \ i--; \ } \ return i != 0; \ diff --git a/gxp-mcu-firmware.c b/gxp-mcu-firmware.c index 6c39e52..3c85d5e 100644 --- a/gxp-mcu-firmware.c +++ b/gxp-mcu-firmware.c @@ -299,6 +299,8 @@ err_lpm_down: */ static int gxp_mcu_firmware_run_locked(struct gxp_mcu_firmware *mcu_fw) { + struct gxp_dev *gxp = mcu_fw->gxp; + struct gxp_mcu *mcu = container_of(mcu_fw, struct gxp_mcu, fw); int ret; lockdep_assert_held(&mcu_fw->lock); @@ -307,6 +309,11 @@ static int gxp_mcu_firmware_run_locked(struct gxp_mcu_firmware *mcu_fw) if (ret) return ret; + ret = gxp_kci_set_device_properties(&mcu->kci, &gxp->device_prop); + if (ret) + dev_warn(gxp->dev, "Failed to pass device_prop to fw: %d\n", + ret); + mcu_fw->status = GCIP_FW_VALID; return 0; } diff --git a/gxp-mcu-fs.c b/gxp-mcu-fs.c index dbad6ca..a31026c 100644 --- a/gxp-mcu-fs.c +++ b/gxp-mcu-fs.c @@ -117,6 +117,26 @@ out: return ret; } +static int gxp_ioctl_set_device_properties( + struct gxp_dev *gxp, + struct gxp_set_device_properties_ioctl __user *argp) +{ + struct gxp_dev_prop *device_prop = &gxp->device_prop; + struct gxp_set_device_properties_ioctl ibuf; + + if (copy_from_user(&ibuf, argp, sizeof(ibuf))) + return -EFAULT; + + mutex_lock(&device_prop->lock); + + memcpy(&device_prop->opaque, &ibuf.opaque, sizeof(device_prop->opaque)); + device_prop->initialized = true; + + mutex_unlock(&device_prop->lock); + + return 0; +} + static inline enum gcip_telemetry_type to_gcip_telemetry_type(u8 type) { if (type == GXP_TELEMETRY_TYPE_LOGGING) @@ -180,6 +200,9 @@ long gxp_mcu_ioctl(struct file *file, uint cmd, ulong arg) case GXP_MAILBOX_UCI_RESPONSE: ret = gxp_ioctl_uci_response(client, argp); break; + case GXP_SET_DEVICE_PROPERTIES: + ret = gxp_ioctl_set_device_properties(client->gxp, argp); + break; default: ret = -ENOTTY; /* unknown command */ } @@ -9,9 +9,11 @@ #include <linux/bits.h> #include <linux/io.h> #include <linux/pm_runtime.h> +#include <linux/thermal.h> /* for fixing bug in gs_tmu_v3 */ #include <linux/types.h> #include <linux/workqueue.h> #include <soc/google/exynos_pm_qos.h> +#include <soc/google/gs_tmu_v3.h> #include <gcip/gcip-pm.h> @@ -64,7 +66,7 @@ static struct gxp_pm_device_ops gxp_aur_ops = { static int gxp_pm_blkpwr_up(struct gxp_dev *gxp) { - int ret = 0; + int ret; /* * This function is equivalent to pm_runtime_get_sync, but will prevent @@ -72,27 +74,38 @@ static int gxp_pm_blkpwr_up(struct gxp_dev *gxp) * only returns either 0 for success or an errno on failure. */ ret = pm_runtime_resume_and_get(gxp->dev); - if (ret) + if (ret) { dev_err(gxp->dev, "pm_runtime_resume_and_get returned %d during blk up\n", ret); - return ret; + return ret; + } + /* Inform TMU the block is up. */ + ret = set_acpm_tj_power_status(TZ_AUR, true); + if (ret) { + pm_runtime_put_sync(gxp->dev); + dev_err(gxp->dev, + "set Tj power status on blk up failed: %d\n", ret); + return ret; + } + return 0; } static int gxp_pm_blkpwr_down(struct gxp_dev *gxp) { - int ret = 0; + int ret; - /* - * Need to put TOP LPM into active state before blk off - * b/189396709 - */ + /* Need to put TOP LPM into active state before blk off. */ if (!gxp_lpm_wait_state_eq(gxp, LPM_PSM_TOP, LPM_ACTIVE_STATE)) { dev_err(gxp->dev, "failed to force TOP LPM to PS0 during blk down\n"); return -EAGAIN; } + ret = set_acpm_tj_power_status(TZ_AUR, false); + if (ret) + dev_err(gxp->dev, + "set Tj power status on blk down failed: %d\n", ret); ret = pm_runtime_put_sync(gxp->dev); if (ret) /* @@ -126,16 +126,32 @@ static void gxp_uci_mailbox_manager_release_unconsumed_async_resps( /* * From here it is guaranteed that no responses will access @vd and be handled by arrived * or timedout callbacks. Therefore, @dest_queue will not be changed anymore. + * + * We don't have to care about the `gxp_uci_wait_async_response` function is being called + * in the middle because the meaning of this function is called is that @vd is being + * released and the `gxp_uci_wait_async_response` function will never be called anymore. */ - /* Clean up unconsumed responses in the @dest_queue. */ + /* + * Clean up responses in the @dest_queue. + * Responses in this queue are arrived/timedout which means they are removed from the + * @wait_queue and put into the @dest_queue. However, the runtime hasn't consumed them via + * the `gxp_uci_wait_async_response` function yet. Therefore, we have to remove them from + * the queue and release their awaiter. + */ list_for_each_entry_safe ( cur, nxt, &vd->mailbox_resp_queues[UCI_RESOURCE_ID].dest_queue, dest_list_entry) { list_del(&cur->dest_list_entry); + gcip_mailbox_release_awaiter(cur->awaiter); } - /* Clean up @wait_queue and release awaiters. */ + /* + * Clean up responses in the @wait_queue. + * Responses in this queue are not arrived/timedout yet which means they are still in the + * @wait_queue and not put into the @dest_queue. Therefore, we have to remove them from the + * queue and release their awaiter. + */ list_for_each_entry_safe ( cur, nxt, &vd->mailbox_resp_queues[UCI_RESOURCE_ID].wait_queue, wait_list_entry) { @@ -164,6 +164,38 @@ static void unmap_resource(struct gxp_virtual_device *vd, } /* + * System config region needs to be mapped as first page RO and remaining RW. + * + * Use unmap_resource() to release mapped resource. + */ +static int map_sys_cfg_resource(struct gxp_virtual_device *vd, + struct gxp_mapped_resource *res) +{ + struct gxp_dev *gxp = vd->gxp; + int ret; + const size_t ro_size = PAGE_SIZE; + + if (res->daddr == 0) + return 0; + if (res->size != GXP_FW_DATA_SYSCFG_SIZE) { + dev_err(gxp->dev, "invalid system cfg size: %#llx", res->size); + return -EINVAL; + } + ret = gxp_iommu_map(gxp, vd->domain, res->daddr, res->paddr, ro_size, + IOMMU_READ); + if (ret) + return ret; + ret = gxp_iommu_map(gxp, vd->domain, res->daddr + ro_size, + res->paddr + ro_size, res->size - ro_size, + IOMMU_READ | IOMMU_WRITE); + if (ret) { + gxp_iommu_unmap(gxp, vd->domain, res->daddr, ro_size); + return ret; + } + return 0; +} + +/* * Assigns @res's IOVA, size from image config. */ static void assign_resource(struct gxp_mapped_resource *res, @@ -245,15 +277,10 @@ static int map_cfg_regions(struct gxp_virtual_device *vd, goto err_unmap_vd; } assign_resource(&res, img_cfg, SYS_CFG_REGION_IDX); - if (res.size != GXP_FW_DATA_SYSCFG_SIZE) { - dev_err(gxp->dev, "invalid system cfg size: %#llx", res.size); - ret = -EINVAL; - goto err_unmap_vd; - } res.vaddr = gxp_fw_data_system_cfg(gxp); offset = res.vaddr - pool.vaddr; res.paddr = pool.paddr + offset; - ret = map_resource(vd, &res); + ret = map_sys_cfg_resource(vd, &res); if (ret) { dev_err(gxp->dev, "map sys config %pad -> offset %#zx failed", &res.daddr, offset); @@ -1200,6 +1227,26 @@ int gxp_vd_virt_core_to_phys_core(struct gxp_virtual_device *vd, u16 virt_core) return -EINVAL; } +int gxp_vd_phys_core_to_virt_core(struct gxp_virtual_device *vd, u32 phys_core) +{ + struct gxp_dev *gxp = vd->gxp; + + lockdep_assert_held(&vd->debug_dump_lock); + + if (!gxp_is_direct_mode(gxp)) { + dev_dbg(gxp->dev, "%s supported only in direct mode.\n", + __func__); + return -EINVAL; + } + + if (!(vd->core_list & BIT(phys_core))) { + dev_dbg(gxp->dev, "No mapping for physical core %u\n", + phys_core); + return -EINVAL; + } + return hweight_long(vd->core_list & (BIT(phys_core) - 1)); +} + int gxp_vd_mapping_store(struct gxp_virtual_device *vd, struct gxp_mapping *map) { struct rb_node **link; @@ -235,6 +235,22 @@ void gxp_vd_stop(struct gxp_virtual_device *vd); int gxp_vd_virt_core_to_phys_core(struct gxp_virtual_device *vd, u16 virt_core); /** + * gxp_vd_phys_core_to_virt_core() -Returns the virtual core ID for the specified + * @phys_core belonging to this virtual device. + * @vd: The virtual device for which virtual core ID is requested for. + * @phys_core: Physical core_id corresponding to which virtual core ID is requested. + * + * This function works only in direct mode. The caller must have locked + * vd->debug_dump_lock before calling this function. + * + * Return: + * * -EINVAL - If no virtual core ID found for @phys_core or if the function + * was not invoked in direct mode. + * * Otherwise - Returns the virtual core ID for the given @phys_core. + */ +int gxp_vd_phys_core_to_virt_core(struct gxp_virtual_device *vd, u32 phys_core); + +/** * gxp_vd_mapping_store() - Store a mapping in a virtual device's records * @vd: The virtual device @map was created for and will be stored in * @map: The mapping to store @@ -13,7 +13,7 @@ /* Interface Version */ #define GXP_INTERFACE_VERSION_MAJOR 1 -#define GXP_INTERFACE_VERSION_MINOR 12 +#define GXP_INTERFACE_VERSION_MINOR 13 #define GXP_INTERFACE_VERSION_BUILD 0 /* @@ -1027,4 +1027,21 @@ struct gxp_register_invalidated_eventfd_ioctl { #define GXP_UNREGISTER_INVALIDATED_EVENTFD \ _IOW(GXP_IOCTL_BASE, 36, struct gxp_register_invalidated_eventfd_ioctl) +/* The size of device properties pre-agreed with firmware */ +#define GXP_DEV_PROP_SIZE 256 +/* + * struct gxp_set_device_properties_ioctl + * @opaque: Device properties defined by runtime and firmware. + */ +struct gxp_set_device_properties_ioctl { + __u8 opaque[GXP_DEV_PROP_SIZE]; +}; + +/* + * Registers device properties which will be passed down to firmware on every + * MCU boot. + */ +#define GXP_SET_DEVICE_PROPERTIES \ + _IOW(GXP_IOCTL_BASE, 37, struct gxp_set_device_properties_ioctl) + #endif /* __GXP_H__ */ |