diff options
author | Aurora pro automerger <aurora-pro-automerger@google.com> | 2023-02-07 08:48:30 +0000 |
---|---|---|
committer | davidchiang <davidchiang@google.com> | 2023-02-09 06:53:21 +0000 |
commit | b76197f77494d3879a181690558349a4aedb66c6 (patch) | |
tree | 9338535eeb63dd814fbb66c344a450f0dc788ee9 | |
parent | 51c89d9e9a7664ff4068fa1405fca5a5fe60aac0 (diff) | |
download | gs201-b76197f77494d3879a181690558349a4aedb66c6.tar.gz |
gxp: [Copybara Auto Merge] Merge branch 'gs201-u' into 'android13-gs-pixel-5.10-udc'android-u-preview-2_r0.2android-u-beta-1_r0.5android-u-beta-1_r0.4android-u-beta-1_r0.3android-gs-raviole-5.10-u-preview-2android-gs-raviole-5.10-u-beta1android-gs-pantah-5.10-u-beta1android-gs-bluejay-5.10-u-beta1
gcip: introduce before_enqueue_wait_list
Bug: 267713283
gcip: Add a new KCI code for thermal control
Bug: 266837631
gcip: Add a new KCI code for fw tracing level request
Bug: 262916889
gcip: fix up DMA fence macros
GCIP_HEADERS_REV_ID: 16235f58e3f50f260c7b13f939857a414fc7eb21
gxp: fix up HAS_TPU_EXT
gxp: telemetry refactor for config_version 2
Bug: 266886853
gxp: fix deleting async_resp before putting
Bug: 267713283 (repeat)
gxp: define and use common interface for iommu_map
Bug: 248436918
gxp: Merge identical parts in [callisto|europa]-platform.c.
Bug: 249918544
gxp: bump interface version to 1.8
gxp: allocate domain pool according to mode
Bug: 267714051
gxp: remove fw data init from debugfs firmware run
gxp: guard core INT and reset with core_boot
Bug: 267713333
Bug: 267713028
gxp: fix up COPY_FIELDS macro in firmware-data
gxp: handle sync fence ioctl calls
Bug: 258876786
gxp: associate DMA fence with VD
Bug: 264855736
gcip: call before_enqueue_wait_list
Bug: 267713283 (repeat)
GCIP_MAIN_REV_ID: 442aa3a49affc15c9db72240cd2d0692b242a82a
GitOrigin-RevId: c547ad68da23508ea20b3d67ecf9fdd3d74fbb79
Change-Id: I907e4bac60a0da03101854d06c66d20f92621598
-rw-r--r-- | gcip-kernel-driver/drivers/gcip/gcip-mailbox.c | 9 | ||||
-rw-r--r-- | gcip-kernel-driver/include/gcip/gcip-dma-fence.h | 7 | ||||
-rw-r--r-- | gcip-kernel-driver/include/gcip/gcip-kci.h | 2 | ||||
-rw-r--r-- | gcip-kernel-driver/include/gcip/gcip-mailbox.h | 16 | ||||
-rw-r--r-- | gxp-common-platform.c | 74 | ||||
-rw-r--r-- | gxp-config.h | 11 | ||||
-rw-r--r-- | gxp-debugfs.c | 7 | ||||
-rw-r--r-- | gxp-dma-fence.c | 22 | ||||
-rw-r--r-- | gxp-dma-iommu.c | 12 | ||||
-rw-r--r-- | gxp-dma.h | 19 | ||||
-rw-r--r-- | gxp-firmware-data.c | 98 | ||||
-rw-r--r-- | gxp-firmware.c | 2 | ||||
-rw-r--r-- | gxp-vd.c | 47 | ||||
-rw-r--r-- | gxp-vd.h | 10 | ||||
-rw-r--r-- | gxp.h | 2 |
15 files changed, 262 insertions, 76 deletions
diff --git a/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c b/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c index cbb3c80..334a51d 100644 --- a/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c +++ b/gcip-kernel-driver/drivers/gcip/gcip-mailbox.c @@ -111,10 +111,19 @@ static int gcip_mailbox_push_wait_resp(struct gcip_mailbox *mailbox, void *resp, { struct gcip_mailbox_wait_list_elem *entry = kzalloc(sizeof(*entry), GFP_KERNEL); unsigned long flags; + int ret; if (!entry) return -ENOMEM; + if (mailbox->ops->before_enqueue_wait_list) { + ret = mailbox->ops->before_enqueue_wait_list(mailbox, resp, awaiter); + if (ret) { + kfree(entry); + return ret; + } + } + /* Increase a reference of arrived handler. */ if (awaiter) refcount_inc(&awaiter->refs); diff --git a/gcip-kernel-driver/include/gcip/gcip-dma-fence.h b/gcip-kernel-driver/include/gcip/gcip-dma-fence.h index c0a7d68..1d4030a 100644 --- a/gcip-kernel-driver/include/gcip/gcip-dma-fence.h +++ b/gcip-kernel-driver/include/gcip/gcip-dma-fence.h @@ -17,8 +17,9 @@ #define GCIP_FENCE_TIMELINE_NAME_LEN 128 /* Used before accessing the list headed by mgr->fence_list_head. */ -#define GCIP_DMA_FENCE_LIST_LOCK(mgr, flags) spin_lock_irqsave(&mgr->fence_list_lock, flags) -#define GCIP_DMA_FENCE_LIST_UNLOCK(mgr, flags) spin_unlock_irqrestore(&mgr->fence_list_lock, flags) +#define GCIP_DMA_FENCE_LIST_LOCK(mgr, flags) spin_lock_irqsave(&(mgr)->fence_list_lock, flags) +#define GCIP_DMA_FENCE_LIST_UNLOCK(mgr, flags) \ + spin_unlock_irqrestore(&(mgr)->fence_list_lock, flags) /* * A macro to loop through all fences under a gcip_dma_fence_manager. @@ -28,7 +29,7 @@ * This macro must be wrapped by GCIP_DMA_FENCE_LIST_(UN)LOCK. */ #define gcip_for_each_fence(mgr, gfence) \ - list_for_each_entry(gfence, &mgr->fence_list_head, fence_list) + list_for_each_entry(gfence, &(mgr)->fence_list_head, fence_list) #define to_gcip_fence(fence) container_of(fence, struct gcip_dma_fence, fence) diff --git a/gcip-kernel-driver/include/gcip/gcip-kci.h b/gcip-kernel-driver/include/gcip/gcip-kci.h index c95d6a7..03cc078 100644 --- a/gcip-kernel-driver/include/gcip/gcip-kci.h +++ b/gcip-kernel-driver/include/gcip/gcip-kci.h @@ -97,6 +97,8 @@ enum gcip_kci_code { GCIP_KCI_CODE_RELEASE_VMBOX = 16, GCIP_KCI_CODE_LINK_OFFLOAD_VMBOX = 17, GCIP_KCI_CODE_UNLINK_OFFLOAD_VMBOX = 18, + GCIP_KCI_CODE_FIRMWARE_TRACING_LEVEL = 19, + GCIP_KCI_CODE_THERMAL_CONTROL = 20, GCIP_KCI_CODE_RKCI_ACK = 256, }; diff --git a/gcip-kernel-driver/include/gcip/gcip-mailbox.h b/gcip-kernel-driver/include/gcip/gcip-mailbox.h index e81cfb9..649b574 100644 --- a/gcip-kernel-driver/include/gcip/gcip-mailbox.h +++ b/gcip-kernel-driver/include/gcip/gcip-mailbox.h @@ -260,6 +260,22 @@ struct gcip_mailbox_ops { */ int (*wait_for_cmd_queue_not_full)(struct gcip_mailbox *mailbox); /* + * This callback will be called before putting the @resp into @mailbox->wait_list and + * putting @cmd of @resp into the command queue. After this callback returns, the consumer + * is able to start processing it and the mailbox is going to wait for it. Therefore, this + * callback is the final checkpoint of deciding whether it is good to wait for the response + * or not. If you don't want to wait for it, return a non-zero value error. + * + * If the implement side has its own wait queue, this callback is suitable to put @resp or + * @awaiter into that. + * + * If @resp is synchronous, @awaiter will be NULL. + * + * Context: normal. + */ + int (*before_enqueue_wait_list)(struct gcip_mailbox *mailbox, void *resp, + struct gcip_mailbox_resp_awaiter *awaiter); + /* * This callback will be called after putting the @cmd to the command queue. It can be used * for triggering the doorbell. Also, @mailbox->cur_seq will be increased by the return * value. If error occurs, returns negative value and @mailbox->cur_seq will not be changed diff --git a/gxp-common-platform.c b/gxp-common-platform.c index e8c5572..66be9c0 100644 --- a/gxp-common-platform.c +++ b/gxp-common-platform.c @@ -29,6 +29,7 @@ #include "gxp-core-telemetry.h" #include "gxp-debug-dump.h" #include "gxp-debugfs.h" +#include "gxp-dma-fence.h" #include "gxp-dma.h" #include "gxp-dmabuf.h" #include "gxp-domain-pool.h" @@ -46,8 +47,7 @@ #include "gxp-wakelock.h" #include "gxp.h" -#if (IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_ANDROID)) && !IS_ENABLED(CONFIG_GXP_GEM5) -#define HAS_TPU_EXT +#if HAS_TPU_EXT #include <soc/google/tpu-ext.h> #endif @@ -870,7 +870,7 @@ static int gxp_disable_core_telemetry(struct gxp_client *client, return ret; } -#ifdef HAS_TPU_EXT +#if HAS_TPU_EXT /* * Map TPU mailboxes to IOVA. @@ -1539,6 +1539,57 @@ out_unlock_client_semaphore: return ret; } +static int +gxp_create_sync_fence(struct gxp_client *client, + struct gxp_create_sync_fence_data __user *datap) +{ + struct gxp_dev *gxp = client->gxp; + struct gxp_create_sync_fence_data data; + int ret; + + if (copy_from_user(&data, (void __user *)datap, sizeof(data))) + return -EFAULT; + down_read(&client->semaphore); + if (client->vd) { + ret = gxp_dma_fence_create(gxp, client->vd, &data); + } else { + dev_warn(gxp->dev, "client creating sync fence has no VD"); + ret = -EINVAL; + } + up_read(&client->semaphore); + if (ret) + return ret; + + if (copy_to_user((void __user *)datap, &data, sizeof(data))) + ret = -EFAULT; + return ret; +} + +static int +gxp_signal_sync_fence(struct gxp_signal_sync_fence_data __user *datap) +{ + struct gxp_signal_sync_fence_data data; + + if (copy_from_user(&data, (void __user *)datap, sizeof(data))) + return -EFAULT; + return gcip_dma_fence_signal(data.fence, data.error, false); +} + +static int gxp_sync_fence_status(struct gxp_sync_fence_status __user *datap) +{ + struct gxp_sync_fence_status data; + int ret; + + if (copy_from_user(&data, (void __user *)datap, sizeof(data))) + return -EFAULT; + ret = gcip_dma_fence_status(data.fence, &data.status); + if (ret) + return ret; + if (copy_to_user((void __user *)datap, &data, sizeof(data))) + ret = -EFAULT; + return ret; +} + static int gxp_register_invalidated_eventfd( struct gxp_client *client, struct gxp_register_invalidated_eventfd_ioctl __user *argp) @@ -1672,6 +1723,15 @@ static long gxp_ioctl(struct file *file, uint cmd, ulong arg) case GXP_TRIGGER_DEBUG_DUMP: ret = gxp_trigger_debug_dump(client, argp); break; + case GXP_CREATE_SYNC_FENCE: + ret = gxp_create_sync_fence(client, argp); + break; + case GXP_SIGNAL_SYNC_FENCE: + ret = gxp_signal_sync_fence(argp); + break; + case GXP_SYNC_FENCE_STATUS: + ret = gxp_sync_fence_status(argp); + break; case GXP_REGISTER_INVALIDATED_EVENTFD: ret = gxp_register_invalidated_eventfd(client, argp); break; @@ -1960,8 +2020,12 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de ret = -ENOMEM; goto err_debug_dump_exit; } - ret = gxp_domain_pool_init(gxp, gxp->domain_pool, - GXP_NUM_PREALLOCATED_DOMAINS); + if (gxp_is_direct_mode(gxp)) + ret = gxp_domain_pool_init(gxp, gxp->domain_pool, + GXP_NUM_CORES); + else + ret = gxp_domain_pool_init(gxp, gxp->domain_pool, + GXP_NUM_SHARED_SLICES); if (ret) { dev_err(dev, "Failed to initialize IOMMU domain pool (ret=%d)\n", diff --git a/gxp-config.h b/gxp-config.h index 69adb67..dbc2d24 100644 --- a/gxp-config.h +++ b/gxp-config.h @@ -18,8 +18,6 @@ #endif /* unknown */ -#define GXP_NUM_PREALLOCATED_DOMAINS GXP_NUM_CORES - #if defined(CONFIG_GXP_ZEBU) || defined(CONFIG_GXP_IP_ZEBU) #define GXP_TIME_DELAY_FACTOR 20 #else @@ -42,4 +40,13 @@ #define GXP_HAS_MCU 1 #endif +/* + * Only supports interop with TPU when + * 1. Unit testing, or + * 2. Production on Android (to exclude vanilla Linux for bringup) but not GEM5. + */ +#define HAS_TPU_EXT \ + ((IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_ANDROID)) && \ + !IS_ENABLED(CONFIG_GXP_GEM5)) + #endif /* __GXP_CONFIG_H__ */ diff --git a/gxp-debugfs.c b/gxp-debugfs.c index 47a45a1..fa1685e 100644 --- a/gxp-debugfs.c +++ b/gxp-debugfs.c @@ -167,13 +167,6 @@ static int gxp_firmware_run_set(void *data, u64 val) } up_write(&gxp->vd_semaphore); - /* - * Cleanup any bad state or corruption the device might've - * caused - */ - gxp_fw_data_destroy(gxp); - gxp_fw_data_init(gxp); - client = gxp_client_create(gxp); if (IS_ERR(client)) { dev_err(gxp->dev, "Failed to create client\n"); diff --git a/gxp-dma-fence.c b/gxp-dma-fence.c index 900ea23..7bcc11b 100644 --- a/gxp-dma-fence.c +++ b/gxp-dma-fence.c @@ -22,7 +22,12 @@ static const char *gxp_get_driver_name(struct dma_fence *fence) static void gxp_dma_fence_release(struct dma_fence *fence) { struct gxp_dma_fence *gxp_fence = to_gxp_fence(fence); + struct gxp_virtual_device *vd = gxp_fence->vd; + mutex_lock(&vd->fence_list_lock); + list_del(&gxp_fence->fence_list); + mutex_unlock(&vd->fence_list_lock); + gxp_vd_put(vd); gcip_dma_fence_exit(&gxp_fence->gfence); kfree(gxp_fence); } @@ -35,6 +40,19 @@ static const struct dma_fence_ops gxp_dma_fence_ops = { .release = gxp_dma_fence_release, }; +static int gxp_dma_fence_after_init(struct gcip_dma_fence *gfence) +{ + struct gxp_dma_fence *gxp_fence = + container_of(gfence, struct gxp_dma_fence, gfence); + struct gxp_virtual_device *vd = gxp_fence->vd; + + mutex_lock(&vd->fence_list_lock); + list_add_tail(&gxp_fence->fence_list, &vd->gxp_fence_list); + mutex_unlock(&vd->fence_list_lock); + + return 0; +} + int gxp_dma_fence_create(struct gxp_dev *gxp, struct gxp_virtual_device *vd, struct gxp_create_sync_fence_data *datap) { @@ -42,6 +60,7 @@ int gxp_dma_fence_create(struct gxp_dev *gxp, struct gxp_virtual_device *vd, .timeline_name = datap->timeline_name, .ops = &gxp_dma_fence_ops, .seqno = datap->seqno, + .after_init = gxp_dma_fence_after_init, }; struct gxp_dma_fence *gxp_fence = kzalloc(sizeof(*gxp_fence), GFP_KERNEL); @@ -50,8 +69,7 @@ int gxp_dma_fence_create(struct gxp_dev *gxp, struct gxp_virtual_device *vd, if (!gxp_fence) return -ENOMEM; - /* TODO(b/264855736): add VD association support */ - + gxp_fence->vd = gxp_vd_get(vd); ret = gcip_dma_fence_init(gxp->gfence_mgr, &gxp_fence->gfence, &data); if (!ret) datap->fence = data.fence; diff --git a/gxp-dma-iommu.c b/gxp-dma-iommu.c index 3dfd70b..94a78b3 100644 --- a/gxp-dma-iommu.c +++ b/gxp-dma-iommu.c @@ -201,6 +201,18 @@ struct gxp_iommu_domain *gxp_iommu_get_domain_for_dev(struct gxp_dev *gxp) return gdomain; } +int gxp_iommu_map(struct gxp_dev *gxp, struct gxp_iommu_domain *gdomain, + unsigned long iova, phys_addr_t paddr, size_t size, int prot) +{ + return iommu_map(gdomain->domain, iova, paddr, size, prot); +} + +void gxp_iommu_unmap(struct gxp_dev *gxp, struct gxp_iommu_domain *gdomain, + unsigned long iova, size_t size) +{ + iommu_unmap(gdomain->domain, iova, size); +} + int gxp_dma_init(struct gxp_dev *gxp) { struct gxp_dma_iommu_manager *mgr; @@ -53,6 +53,24 @@ struct gxp_dma_manager { #endif /** + * gxp_iommu_map() - Create mappings in iommu + * @gxp: The GXP device + * @gdomain: The IOMMU domain to create mappings in. + * + * Return: 0 on success or negative value indicating error + */ +int gxp_iommu_map(struct gxp_dev *gxp, struct gxp_iommu_domain *gdomain, + unsigned long iova, phys_addr_t paddr, size_t size, int prot); + +/** + * gxp_iommu_unmap() - Reverts mappings created by gxp_iommu_map() + * @gxp: The GXP device + * @gdomain: The IOMMU domain to revert mappings in. + */ +void gxp_iommu_unmap(struct gxp_dev *gxp, struct gxp_iommu_domain *gdomain, + unsigned long iova, size_t size); + +/** * gxp_dma_init() - Initialize the GXP DMA subsystem * @gxp: The GXP device to initialize DMA for * @@ -356,5 +374,4 @@ uint gxp_iommu_aux_get_pasid(struct gxp_dev *gxp, */ void gxp_iommu_setup_shareability(struct gxp_dev *gxp); - #endif /* __GXP_DMA_H__ */ diff --git a/gxp-firmware-data.c b/gxp-firmware-data.c index 684d08c..4a35ccc 100644 --- a/gxp-firmware-data.c +++ b/gxp-firmware-data.c @@ -22,29 +22,29 @@ * The minimum alignment order (power of 2) of allocations in the firmware data * region. */ -#define FW_DATA_STORAGE_ORDER 3 +#define FW_DATA_STORAGE_ORDER 3 /* A byte pattern to pre-populate the FW region with */ -#define FW_DATA_DEBUG_PATTERN 0x66 +#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 +#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 +#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 +#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 { @@ -595,25 +595,29 @@ static void set_system_cfg_region(struct gxp_dev *gxp, void *sys_cfg) else des_ro->debug_dump_dev_addr = 0; -#define COPY_FIELDS \ +#define COPY_FIELDS(des, ro, rw) \ do { \ - tel_ro->host_status = tel_des->host_status; \ - tel_ro->buffer_addr = tel_des->buffer_addr; \ - tel_ro->buffer_size = tel_des->buffer_size; \ - tel_rw->device_status = tel_des->device_status; \ - tel_rw->data_available = tel_des->watermark_level; \ + ro->host_status = des->host_status; \ + ro->buffer_addr = des->buffer_addr; \ + ro->buffer_size = des->buffer_size; \ + rw->device_status = des->device_status; \ + rw->data_available = des->watermark_level; \ } while (0) for (i = 0; i < GXP_NUM_CORES; i++) { tel_ro = &des_ro->telemetry_desc.per_core_loggers[i]; tel_rw = &des_rw->telemetry_desc.per_core_loggers[i]; tel_des = &descriptor->per_core_loggers[i]; - COPY_FIELDS; + COPY_FIELDS(tel_des, tel_ro, tel_rw); tel_ro = &des_ro->telemetry_desc.per_core_tracers[i]; tel_rw = &des_rw->telemetry_desc.per_core_tracers[i]; tel_des = &descriptor->per_core_tracers[i]; - COPY_FIELDS; + COPY_FIELDS(tel_des, tel_ro, tel_rw); } #undef COPY_FIELDS + + /* Update the global descriptors. */ + gxp->data_mgr->sys_desc_ro = des_ro; + gxp->data_mgr->sys_desc_rw = des_rw; } static struct app_metadata * @@ -632,7 +636,7 @@ _gxp_fw_data_create_app(struct gxp_dev *gxp, struct gxp_virtual_device *vd) * initialization of legacy mode, and have here copy the values to the * config region. */ - if (vd->vdid == 0) + if (vd->vdid == 1) set_system_cfg_region(gxp, vd->sys_cfg.vaddr); app = kzalloc(sizeof(*app), GFP_KERNEL); if (!app) @@ -782,9 +786,9 @@ int gxp_fw_data_init(struct gxp_dev *gxp) goto err; /* Shared firmware data memory region */ - mgr->allocator = mem_alloc_create(gxp, mgr->fw_data_virt, - gxp->fwdatabuf.daddr, - gxp->fwdatabuf.size); + 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"); @@ -902,13 +906,14 @@ int gxp_fw_data_set_core_telemetry_descriptors(struct gxp_dev *gxp, u8 type, /* Validate that the provided IOVAs are addressable (i.e. 32-bit) */ for (core = 0; core < GXP_NUM_CORES; core++) { if (buffers && buffers[core].dsp_addr > U32_MAX && - buffers[core].size == per_buffer_size) + buffers[core].size == per_buffer_size) return -EINVAL; } for (core = 0; core < GXP_NUM_CORES; core++) { core_descriptors[core].host_status = host_status; - core_descriptors[core].buffer_addr = (u32)buffers[core].dsp_addr; + core_descriptors[core].buffer_addr = + (u32)buffers[core].dsp_addr; core_descriptors[core].buffer_size = per_buffer_size; } } else { @@ -922,15 +927,13 @@ int gxp_fw_data_set_core_telemetry_descriptors(struct gxp_dev *gxp, u8 type, return 0; } -u32 gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp, uint core, - u8 type) +static u32 +gxp_fw_data_get_core_telemetry_device_status_legacy(struct gxp_dev *gxp, + uint core, u8 type) { struct gxp_core_telemetry_descriptor *descriptor = gxp->data_mgr->core_telemetry_mem.host_addr; - if (core >= GXP_NUM_CORES) - return 0; - switch (type) { case GXP_TELEMETRY_TYPE_LOGGING: return descriptor->per_core_loggers[core].device_status; @@ -940,3 +943,36 @@ u32 gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp, uint core, 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: + return des_rw->telemetry_desc.per_core_loggers[core] + .device_status; + case GXP_TELEMETRY_TYPE_TRACING: + return des_rw->telemetry_desc.per_core_tracers[core] + .device_status; + default: + return 0; + } +} + +u32 gxp_fw_data_get_core_telemetry_device_status(struct gxp_dev *gxp, uint core, + u8 type) +{ + if (core >= GXP_NUM_CORES) + return 0; + + 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); + } else { + return gxp_fw_data_get_core_telemetry_device_status_legacy( + gxp, core, type); + } +} diff --git a/gxp-firmware.c b/gxp-firmware.c index 32d5dc3..4a59a13 100644 --- a/gxp-firmware.c +++ b/gxp-firmware.c @@ -867,9 +867,9 @@ static int gxp_firmware_setup(struct gxp_dev *gxp, gxp_firmware_unload(gxp, core); return ret; } + enable_core_interrupts(gxp, phys_core); } - enable_core_interrupts(gxp, phys_core); return ret; } @@ -120,26 +120,25 @@ static void unmap_ns_region(struct gxp_virtual_device *vd, dma_addr_t daddr) static int map_core_shared_buffer(struct gxp_virtual_device *vd) { struct gxp_dev *gxp = vd->gxp; - struct iommu_domain *domain = vd->domain->domain; const size_t shared_size = GXP_SHARED_SLICE_SIZE; if (!gxp->shared_buf.paddr) return 0; - return iommu_map(domain, gxp->shared_buf.daddr, - gxp->shared_buf.paddr + shared_size * vd->slice_index, - shared_size, IOMMU_READ | IOMMU_WRITE); + return gxp_iommu_map(gxp, vd->domain, gxp->shared_buf.daddr, + gxp->shared_buf.paddr + + shared_size * vd->slice_index, + shared_size, IOMMU_READ | IOMMU_WRITE); } /* Reverts map_core_shared_buffer. */ static void unmap_core_shared_buffer(struct gxp_virtual_device *vd) { struct gxp_dev *gxp = vd->gxp; - struct iommu_domain *domain = vd->domain->domain; const size_t shared_size = GXP_SHARED_SLICE_SIZE; if (!gxp->shared_buf.paddr) return; - iommu_unmap(domain, gxp->shared_buf.daddr, shared_size); + gxp_iommu_unmap(gxp, vd->domain, gxp->shared_buf.daddr, shared_size); } /* Maps @res->daddr to @res->paddr to @vd->domain. */ @@ -148,8 +147,8 @@ static int map_resource(struct gxp_virtual_device *vd, { if (res->daddr == 0) return 0; - return iommu_map(vd->domain->domain, res->daddr, res->paddr, res->size, - IOMMU_READ | IOMMU_WRITE); + return gxp_iommu_map(vd->gxp, vd->domain, res->daddr, res->paddr, res->size, + IOMMU_READ | IOMMU_WRITE); } /* Reverts map_resource. */ @@ -158,7 +157,7 @@ static void unmap_resource(struct gxp_virtual_device *vd, { if (res->daddr == 0) return; - iommu_unmap(vd->domain->domain, res->daddr, res->size); + gxp_iommu_unmap(vd->gxp, vd->domain, res->daddr, res->size); } /* @@ -377,14 +376,14 @@ static int alloc_and_map_fw_image(struct gxp_dev *gxp, struct gxp_virtual_device *vd) { size_t ro_size = vd->fw_ro_size, rw_size; - struct iommu_domain *domain = vd->domain->domain; + struct gxp_iommu_domain *gdomain = vd->domain; int i, ret; /* Maps all FW regions together and no rwdata_sgt in this case. */ if (ro_size == gxp->fwbufs[0].size) - return iommu_map(domain, gxp->fwbufs[0].daddr, - gxp->fwbufs[0].paddr, ro_size * GXP_NUM_CORES, - IOMMU_READ | IOMMU_WRITE); + return gxp_iommu_map(gxp, gdomain, gxp->fwbufs[0].daddr, + gxp->fwbufs[0].paddr, ro_size * GXP_NUM_CORES, + IOMMU_READ | IOMMU_WRITE); dev_info(gxp->dev, "mapping firmware RO size %#zx", ro_size); rw_size = gxp->fwbufs[0].size - ro_size; @@ -399,9 +398,9 @@ static int alloc_and_map_fw_image(struct gxp_dev *gxp, } } for (i = 0; i < GXP_NUM_CORES; i++) { - ret = iommu_map(domain, gxp->fwbufs[i].daddr, - gxp->fwbufs[i].paddr, ro_size, - IOMMU_READ | IOMMU_WRITE); + ret = gxp_iommu_map(gxp, gdomain, gxp->fwbufs[i].daddr, + gxp->fwbufs[i].paddr, ro_size, + IOMMU_READ | IOMMU_WRITE); if (ret) { dev_err(gxp->dev, "map firmware RO for core %d failed", i); @@ -414,7 +413,7 @@ static int alloc_and_map_fw_image(struct gxp_dev *gxp, if (ret) { dev_err(gxp->dev, "map firmware RW for core %d failed", i); - iommu_unmap(domain, gxp->fwbufs[i].daddr, ro_size); + gxp_iommu_unmap(gxp, gdomain, gxp->fwbufs[i].daddr, ro_size); goto err_unmap; } } @@ -422,7 +421,7 @@ static int alloc_and_map_fw_image(struct gxp_dev *gxp, err_unmap: while (i--) { - iommu_unmap(domain, gxp->fwbufs[i].daddr, ro_size); + gxp_iommu_unmap(gxp, gdomain, gxp->fwbufs[i].daddr, ro_size); gxp_dma_unmap_iova_sgt(gxp, vd->domain, gxp->fwbufs[i].daddr + ro_size, vd->rwdata_sgt[i]); @@ -440,17 +439,16 @@ static void unmap_and_free_fw_image(struct gxp_dev *gxp, struct gxp_virtual_device *vd) { size_t ro_size = vd->fw_ro_size; - struct iommu_domain *domain = vd->domain->domain; + struct gxp_iommu_domain *gdomain = vd->domain; int i; if (ro_size == gxp->fwbufs[0].size) { - iommu_unmap(domain, gxp->fwbufs[0].daddr, - ro_size * GXP_NUM_CORES); + gxp_iommu_unmap(gxp, gdomain, gxp->fwbufs[0].daddr, ro_size * GXP_NUM_CORES); return; } for (i = 0; i < GXP_NUM_CORES; i++) { - iommu_unmap(domain, gxp->fwbufs[i].daddr, ro_size); + gxp_iommu_unmap(gxp, gdomain, gxp->fwbufs[i].daddr, ro_size); gxp_dma_unmap_iova_sgt(gxp, vd->domain, gxp->fwbufs[i].daddr + ro_size, vd->rwdata_sgt[i]); @@ -683,6 +681,8 @@ struct gxp_virtual_device *gxp_vd_allocate(struct gxp_dev *gxp, vd->credit = GXP_COMMAND_CREDIT_PER_VD; vd->first_open = true; vd->vdid = atomic_inc_return(&gxp->next_vdid); + mutex_init(&vd->fence_list_lock); + INIT_LIST_HEAD(&vd->gxp_fence_list); vd->domain = gxp_domain_pool_alloc(gxp->domain_pool); if (!vd->domain) { @@ -928,7 +928,8 @@ void gxp_vd_stop(struct gxp_virtual_device *vd) uint lpm_state; lockdep_assert_held(&gxp->vd_semaphore); - if ((vd->state == GXP_VD_OFF || vd->state == GXP_VD_READY || + if (gxp_core_boot && + (vd->state == GXP_VD_OFF || vd->state == GXP_VD_READY || vd->state == GXP_VD_RUNNING) && gxp_pm_get_blk_state(gxp) != AUR_OFF) { /* @@ -10,6 +10,7 @@ #include <linux/iommu.h> #include <linux/list.h> +#include <linux/mutex.h> #include <linux/rbtree.h> #include <linux/refcount.h> #include <linux/rwsem.h> @@ -39,6 +40,11 @@ struct mailbox_resp_queue { spinlock_t lock; /* Waitqueue to wait on if the queue is empty */ wait_queue_head_t waitq; + /* + * If true, the user cannot send requests anymore. + * This must be protected by @lock. + */ + bool wait_queue_closed; }; enum gxp_virtual_device_state { @@ -139,6 +145,10 @@ struct gxp_virtual_device { struct gcip_image_config_parser cfg_parser; /* The config version specified in firmware's image config. */ u32 config_version; + /* Protects @dma_fence_list. */ + struct mutex fence_list_lock; + /* List of GXP DMA fences owned by this VD. */ + struct list_head gxp_fence_list; }; /* @@ -13,7 +13,7 @@ /* Interface Version */ #define GXP_INTERFACE_VERSION_MAJOR 1 -#define GXP_INTERFACE_VERSION_MINOR 7 +#define GXP_INTERFACE_VERSION_MINOR 8 #define GXP_INTERFACE_VERSION_BUILD 0 /* |