summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurora pro automerger <aurora-pro-automerger@google.com>2023-02-07 08:48:30 +0000
committerdavidchiang <davidchiang@google.com>2023-02-09 06:53:21 +0000
commitb76197f77494d3879a181690558349a4aedb66c6 (patch)
tree9338535eeb63dd814fbb66c344a450f0dc788ee9
parent51c89d9e9a7664ff4068fa1405fca5a5fe60aac0 (diff)
downloadgs201-b76197f77494d3879a181690558349a4aedb66c6.tar.gz
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.c9
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-dma-fence.h7
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-kci.h2
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-mailbox.h16
-rw-r--r--gxp-common-platform.c74
-rw-r--r--gxp-config.h11
-rw-r--r--gxp-debugfs.c7
-rw-r--r--gxp-dma-fence.c22
-rw-r--r--gxp-dma-iommu.c12
-rw-r--r--gxp-dma.h19
-rw-r--r--gxp-firmware-data.c98
-rw-r--r--gxp-firmware.c2
-rw-r--r--gxp-vd.c47
-rw-r--r--gxp-vd.h10
-rw-r--r--gxp.h2
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;
diff --git a/gxp-dma.h b/gxp-dma.h
index da7d433..eb131fd 100644
--- a/gxp-dma.h
+++ b/gxp-dma.h
@@ -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;
}
diff --git a/gxp-vd.c b/gxp-vd.c
index adf0daa..2468ca9 100644
--- a/gxp-vd.c
+++ b/gxp-vd.c
@@ -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) {
/*
diff --git a/gxp-vd.h b/gxp-vd.h
index 9d78b45..97e9ccd 100644
--- a/gxp-vd.h
+++ b/gxp-vd.h
@@ -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;
};
/*
diff --git a/gxp.h b/gxp.h
index 676b0b3..afc9f87 100644
--- a/gxp.h
+++ b/gxp.h
@@ -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
/*