summaryrefslogtreecommitdiff
path: root/gcip-kernel-driver/drivers
diff options
context:
space:
mode:
authorAurora pro automerger <aurora-pro-automerger@google.com>2023-02-02 11:46:21 +0000
committerdavidchiang <davidchiang@google.com>2023-02-02 12:17:17 +0000
commit51c89d9e9a7664ff4068fa1405fca5a5fe60aac0 (patch)
tree8fa3c34a8dee0d30896f6efc3effa8f86d313e42 /gcip-kernel-driver/drivers
parent8a4b0d93e1f8b9ae23fb476eef4d43f18bc3cc1d (diff)
downloadgs201-51c89d9e9a7664ff4068fa1405fca5a5fe60aac0.tar.gz
gxp: [Copybara Auto Merge] Merge branch 'gs201-u' into 'android13-gs-pixel-5.10-udc'android-u-preview-2_r0.4android-u-preview-2_r0.3android-gs-pantah-5.10-u-preview-2android-gs-bluejay-5.10-u-preview-2
gcip: use v*alloc without node GCIP_MAIN_REV_ID: e48d8c14dff78d70064f93e5faee61c17b0479c2 gxp: create debug dir root earlier on probe gxp: fix code style/formatting issues gxp: Implement debug dump handling for mcu mode Bug: 265092842 gcip: fix code style/formatting issues GCIP_HEADERS_REV_ID: 8f57799df52bf60cb1805ab5e9ee48034bb139c8 gcip: expose config size calculation to header Bug: 265605775 gcip: sync RKCI codes with fw gcip: update comments of gcip_dma_fence_init Bug: 264220687 gcip: add to_gcip_fence to gcip-dma-fence Bug: 264220687 (repeat) gcip: fix GCIP_DMA_FENCE_LIST_UNLOCK Bug: 258876786 gcip: correct path of gcip-dma-fence.h Bug: 258876786 (repeat) gcip: add gcip-dma-fence.h Bug: 258876786 (repeat) gcip: introduce firmware crash type Bug: 237739631 GCIP_HEADERS_REV_ID: 0a85dc4b06195de6efa46e2ca314548f07f30097 gxp: move core config region to second half of buf gxp: boot status and doorbell for suspend/resume Bug: 265742153 gxp: set VD and core config region Bug: 265742153 (repeat) gxp: use core cfg region for firmware handshake Bug: 265742153 (repeat) gxp: boot with virt_core on per-VD config method Bug: 265742153 (repeat) gxp: only map fwdata region in legacy protocol Bug: 265742153 (repeat) gxp: populate system config on fw data create Bug: 265742153 (repeat) gxp: flush SGT after map iova sgt Bug: 265564221 gxp: remove gxp_vd_phys_core_list gxp: signal eventfd when client is invalidated Bug: 264830822 gxp: introduce GXP_(UN)REGISTER_INVALIDATED_EVENTFD ioctl Bug: 264830822 (repeat) gxp: add create/destroy app legacy functions Bug: 265742153 (repeat) gxp: pass vd to fw_data_create_app Bug: 265742153 (repeat) gxp: add structures for new app config Bug: 265742153 (repeat) gxp: add sys_cfg mapping support Bug: 265605775 (repeat) gxp: all chips/modes have shared region Bug: 265605775 (repeat) gxp: map config regions per image config Bug: 265605775 (repeat) gxp: set shared_buf vaddr Bug: 265605775 (repeat) gxp: map image config NS mappings Bug: 265564221 (repeat) gxp: use per VD scratchpad region Bug: 261797596 gxp: conditionally map FW image region Bug: 265105395 gxp: add lock_class_key to struct client gxp: add image config parser to VD Bug: 265105395 (repeat) gxp: record image config on firmware requested Bug: 265105395 (repeat) gxp: add missing up_read in gxp_debugfs_mailbox gxp: implement vd invalidation Bug: 264831024 gxp: pass timeout_ms to gxp_pm_is_blk_down gxp: set is_firmware_requested on SysFS FW load gxp: set SSMT to bypass in MCU mode Bug: 264950137 Revert "gxp: fetch segment boundaries from ELF header" gxp: add gcip_dma_fence_manager to gxp_dev Bug: 258876786 (repeat) gxp: add gxp-dma-fence support Bug: 258876786 (repeat) gxp: introduce GXP_NAME macro gxp: return vdid on VD allocation ioctl Bug: 264827584 gxp: add VDID support Bug: 264827584 (repeat) gxp: remove a cleanup TODO from vd.h gxp: add refcount to virtual device Bug: 264739996 gxp: add sync fence interfaces Bug: 258876786 (repeat) gxp: detach vd->domain when the state is invalid Bug: 263830035 gxp: call vd_block_unready when failed to run core fw Bug: 263830035 (repeat) gxp: apply clang-format to gxp-vd.c Bug: 263830035 (repeat) gxp: allow debugfs mailbox only with valid vd Bug: 264629015 gxp: add debugfs_client to client_list Bug: 264629015 (repeat) gxp: hold vd_semaphore only when direct mode Bug: 263830035 (repeat) gxp: fix vd_semaphore locking Bug: 263215610 gxp: revert VD state on after_vd_block_ready fail Bug: 263215610 (repeat) gcip: conditionally zero the non-contiguous region gcip: expose config size calculation to header Bug: 265605775 (repeat) gcip: Use strscpy instead of memcpy gcip: enhance image config NS mapping decoding Bug: 265565307 gcip: don't fail dma_fence_init on long name Bug: 264220687 (repeat) gcip: implement gcip_dma_fence_show Bug: 264220687 (repeat) gcip: implement DMA fence status and signal Bug: 264220687 (repeat) gcip: add gcip-dma-fence.c Bug: 258876786 (repeat) GCIP_MAIN_REV_ID: 0a2e7b7e345705db78c8108890781cbe5c8c4eb7 GitOrigin-RevId: 277fffe779cbaf54c2d811928835e9a5ec67e832 Change-Id: Ied761f3000df6a44856db9438d21afd9b3ccb9aa
Diffstat (limited to 'gcip-kernel-driver/drivers')
-rw-r--r--gcip-kernel-driver/drivers/gcip/Makefile10
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-alloc-helper.c6
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-dma-fence.c196
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-image-config.c42
4 files changed, 219 insertions, 35 deletions
diff --git a/gcip-kernel-driver/drivers/gcip/Makefile b/gcip-kernel-driver/drivers/gcip/Makefile
index c3424ee..ab68776 100644
--- a/gcip-kernel-driver/drivers/gcip/Makefile
+++ b/gcip-kernel-driver/drivers/gcip/Makefile
@@ -6,8 +6,14 @@
CONFIG_GCIP ?= m
obj-$(CONFIG_GCIP) += gcip.o
-gcip-objs := gcip-alloc-helper.o gcip-domain-pool.o gcip-firmware.o \
- gcip-image-config.o gcip-kci.o gcip-mailbox.o gcip-mem-pool.o \
+gcip-objs := gcip-alloc-helper.o \
+ gcip-dma-fence.o \
+ gcip-domain-pool.o \
+ gcip-firmware.o \
+ gcip-image-config.o \
+ gcip-kci.o \
+ gcip-mailbox.o \
+ gcip-mem-pool.o \
gcip-telemetry.o
CURRENT_DIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
diff --git a/gcip-kernel-driver/drivers/gcip/gcip-alloc-helper.c b/gcip-kernel-driver/drivers/gcip/gcip-alloc-helper.c
index 33c95e2..85af8e5 100644
--- a/gcip-kernel-driver/drivers/gcip/gcip-alloc-helper.c
+++ b/gcip-kernel-driver/drivers/gcip/gcip-alloc-helper.c
@@ -7,6 +7,7 @@
#include <asm/page.h>
#include <linux/device.h>
+#include <linux/gfp.h>
#include <linux/mm_types.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
@@ -47,7 +48,10 @@ struct sg_table *gcip_alloc_noncontiguous(struct device *dev, size_t size, gfp_t
size = PAGE_ALIGN(size);
count = size >> PAGE_SHIFT;
- mem = vzalloc_node(size, dev_to_node(dev));
+ if (gfp & __GFP_ZERO)
+ mem = vzalloc(size);
+ else
+ mem = vmalloc(size);
if (!mem) {
dev_err(dev, "GCIP noncontiguous alloc size=%#zx failed", size);
goto err_free_sh;
diff --git a/gcip-kernel-driver/drivers/gcip/gcip-dma-fence.c b/gcip-kernel-driver/drivers/gcip/gcip-dma-fence.c
new file mode 100644
index 0000000..4f83670
--- /dev/null
+++ b/gcip-kernel-driver/drivers/gcip/gcip-dma-fence.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GCIP support of DMA fences.
+ *
+ * Copyright (C) 2023 Google LLC
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/dma-fence.h>
+#include <linux/err.h>
+#include <linux/file.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/sync_file.h>
+#include <linux/time.h>
+
+#include <gcip/gcip-dma-fence.h>
+
+#define to_gfence(fence) container_of(fence, struct gcip_dma_fence, fence)
+
+static int _gcip_dma_fence_signal(struct dma_fence *fence, int error, bool ignore_signaled)
+{
+ int ret;
+
+ if (error > 0)
+ error = -error;
+ if (unlikely(error < -MAX_ERRNO))
+ return -EINVAL;
+
+ spin_lock_irq(fence->lock);
+ /* don't signal fence twice */
+ if (unlikely(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))) {
+ ret = ignore_signaled ? 0 : -EBUSY;
+ goto out_unlock;
+ }
+ if (error)
+ dma_fence_set_error(fence, error);
+ ret = dma_fence_signal_locked(fence);
+
+out_unlock:
+ spin_unlock_irq(fence->lock);
+ return ret;
+}
+
+static const char *sync_status_str(int status)
+{
+ if (status < 0)
+ return "error";
+ if (status > 0)
+ return "signaled";
+ return "active";
+}
+
+struct gcip_dma_fence_manager *gcip_dma_fence_manager_create(struct device *dev)
+{
+ struct gcip_dma_fence_manager *mgr = devm_kzalloc(dev, sizeof(*mgr), GFP_KERNEL);
+
+ if (!mgr)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&mgr->fence_list_head);
+ spin_lock_init(&mgr->fence_list_lock);
+ mgr->dev = dev;
+
+ return mgr;
+}
+
+const char *gcip_dma_fence_get_timeline_name(struct dma_fence *fence)
+{
+ struct gcip_dma_fence *gfence = to_gfence(fence);
+
+ return gfence->timeline_name;
+}
+
+bool gcip_dma_fence_always_true(struct dma_fence *fence)
+{
+ return true;
+}
+
+int gcip_dma_fence_init(struct gcip_dma_fence_manager *mgr, struct gcip_dma_fence *gfence,
+ struct gcip_dma_fence_data *data)
+{
+ unsigned long flags;
+ int fd;
+ struct sync_file *sync_file;
+ int ret;
+
+ strscpy(gfence->timeline_name, data->timeline_name, GCIP_FENCE_TIMELINE_NAME_LEN);
+
+ spin_lock_init(&gfence->lock);
+ INIT_LIST_HEAD(&gfence->fence_list);
+ gfence->mgr = mgr;
+
+ dma_fence_init(&gfence->fence, data->ops, &gfence->lock, dma_fence_context_alloc(1),
+ data->seqno);
+ GCIP_DMA_FENCE_LIST_LOCK(mgr, flags);
+ list_add_tail(&gfence->fence_list, &mgr->fence_list_head);
+ GCIP_DMA_FENCE_LIST_UNLOCK(mgr, flags);
+
+ if (data->after_init) {
+ ret = data->after_init(gfence);
+ if (ret) {
+ dev_err(mgr->dev, "DMA fence init failed on after_init: %d", ret);
+ goto err_put_fence;
+ }
+ }
+ fd = get_unused_fd_flags(O_CLOEXEC);
+ if (fd < 0) {
+ ret = fd;
+ dev_err(mgr->dev, "Failed to get FD: %d", ret);
+ goto err_put_fence;
+ }
+ sync_file = sync_file_create(&gfence->fence);
+ if (!sync_file) {
+ dev_err(mgr->dev, "Failed to create sync file");
+ ret = -ENOMEM;
+ goto err_put_fd;
+ }
+ /* sync_file holds the reference to fence, so we can drop our reference. */
+ dma_fence_put(&gfence->fence);
+
+ fd_install(fd, sync_file->file);
+ data->fence = fd;
+ return 0;
+
+err_put_fd:
+ put_unused_fd(fd);
+err_put_fence:
+ dma_fence_put(&gfence->fence);
+ return ret;
+}
+
+void gcip_dma_fence_exit(struct gcip_dma_fence *gfence)
+{
+ unsigned long flags;
+
+ GCIP_DMA_FENCE_LIST_LOCK(gfence->mgr, flags);
+ list_del(&gfence->fence_list);
+ GCIP_DMA_FENCE_LIST_UNLOCK(gfence->mgr, flags);
+}
+
+int gcip_dma_fence_status(int fence, int *status)
+{
+ struct dma_fence *fencep;
+
+ fencep = sync_file_get_fence(fence);
+ if (!fencep)
+ return -EBADF;
+ *status = dma_fence_get_status(fencep);
+ dma_fence_put(fencep);
+ return 0;
+}
+
+int gcip_dma_fence_signal(int fence, int error, bool ignore_signaled)
+{
+ struct dma_fence *fencep;
+ int ret;
+
+ fencep = sync_file_get_fence(fence);
+ if (!fencep)
+ return -EBADF;
+ ret = _gcip_dma_fence_signal(fencep, error, ignore_signaled);
+ dma_fence_put(fencep);
+ return ret;
+}
+
+int gcip_dma_fenceptr_signal(struct gcip_dma_fence *gfence, int error, bool ignore_signaled)
+{
+ return _gcip_dma_fence_signal(&gfence->fence, error, ignore_signaled);
+}
+
+void gcip_dma_fence_show(struct gcip_dma_fence *gfence, struct seq_file *s)
+{
+ struct dma_fence *fence = &gfence->fence;
+
+ spin_lock_irq(&gfence->lock);
+
+ seq_printf(s, "%s-%s %llu-%llu %s", fence->ops->get_driver_name(fence),
+ fence->ops->get_timeline_name(fence), fence->context, fence->seqno,
+ sync_status_str(dma_fence_get_status_locked(fence)));
+
+ if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) {
+ struct timespec64 ts = ktime_to_timespec64(fence->timestamp);
+
+ seq_printf(s, " @%lld.%09ld", (s64)ts.tv_sec, ts.tv_nsec);
+ }
+
+ if (fence->error)
+ seq_printf(s, " err=%d", fence->error);
+
+ spin_unlock_irq(&gfence->lock);
+}
diff --git a/gcip-kernel-driver/drivers/gcip/gcip-image-config.c b/gcip-kernel-driver/drivers/gcip/gcip-image-config.c
index 312bbdc..62acd0b 100644
--- a/gcip-kernel-driver/drivers/gcip/gcip-image-config.c
+++ b/gcip-kernel-driver/drivers/gcip/gcip-image-config.c
@@ -12,28 +12,6 @@
#include <gcip/gcip-image-config.h>
-#define ADDR_SHIFT 12
-#define SIZE_MODE_BIT BIT(ADDR_SHIFT - 1)
-#define SECURE_SIZE_MASK (SIZE_MODE_BIT - 1u)
-#define NS_SIZE_MASK (BIT(ADDR_SHIFT) - 1u)
-#define ADDR_MASK ~(BIT(ADDR_SHIFT) - 1u)
-
-/* used by ns_iommu_mappings */
-#define CONFIG_TO_MBSIZE(a) (((a) & NS_SIZE_MASK) << 20)
-
-/* used by iommu_mappings */
-static inline __u32 config_to_size(__u32 cfg)
-{
- __u32 page_size;
-
- if (cfg & SIZE_MODE_BIT)
- page_size = cfg & SECURE_SIZE_MASK;
- else
- page_size = BIT(cfg & SECURE_SIZE_MASK);
-
- return page_size << PAGE_SHIFT;
-}
-
static int setup_iommu_mappings(struct gcip_image_config_parser *parser,
struct gcip_image_config *config)
{
@@ -49,8 +27,8 @@ static int setup_iommu_mappings(struct gcip_image_config_parser *parser,
ret = -EIO;
goto err;
}
- size = config_to_size(config->iommu_mappings[i].image_config_value);
- paddr = config->iommu_mappings[i].image_config_value & ADDR_MASK;
+ size = gcip_config_to_size(config->iommu_mappings[i].image_config_value);
+ paddr = config->iommu_mappings[i].image_config_value & GCIP_IMG_CFG_ADDR_MASK;
dev_dbg(parser->dev, "Image config adding IOMMU mapping: %pad -> %pap", &daddr,
&paddr);
@@ -74,7 +52,7 @@ static int setup_iommu_mappings(struct gcip_image_config_parser *parser,
err:
while (i--) {
daddr = config->iommu_mappings[i].virt_address;
- size = config_to_size(config->iommu_mappings[i].image_config_value);
+ size = gcip_config_to_size(config->iommu_mappings[i].image_config_value);
parser->ops->unmap(parser->data, daddr, size, GCIP_IMAGE_CONFIG_FLAGS_SECURE);
}
return ret;
@@ -89,7 +67,7 @@ static void clear_iommu_mappings(struct gcip_image_config_parser *parser,
for (i = config->num_iommu_mappings - 1; i >= 0; i--) {
daddr = config->iommu_mappings[i].virt_address;
- size = config_to_size(config->iommu_mappings[i].image_config_value);
+ size = gcip_config_to_size(config->iommu_mappings[i].image_config_value);
dev_dbg(parser->dev, "Image config removing IOMMU mapping: %pad size=%#lx", &daddr,
size);
parser->ops->unmap(parser->data, daddr, size, GCIP_IMAGE_CONFIG_FLAGS_SECURE);
@@ -105,13 +83,13 @@ static int setup_ns_iommu_mappings(struct gcip_image_config_parser *parser,
phys_addr_t paddr = 0;
for (i = 0; i < config->num_ns_iommu_mappings; i++) {
- daddr = config->ns_iommu_mappings[i] & ADDR_MASK;
+ daddr = config->ns_iommu_mappings[i] & GCIP_IMG_CFG_ADDR_MASK;
if (unlikely(!daddr)) {
dev_warn(parser->dev, "Invalid config, device address is zero");
ret = -EIO;
goto err;
}
- size = CONFIG_TO_MBSIZE(config->ns_iommu_mappings[i]);
+ size = gcip_ns_config_to_size(config->ns_iommu_mappings[i]);
dev_dbg(parser->dev, "Image config adding NS IOMMU mapping: %pad -> %pap", &daddr,
&paddr);
if (unlikely(daddr + size <= daddr || paddr + size <= paddr)) {
@@ -128,8 +106,8 @@ static int setup_ns_iommu_mappings(struct gcip_image_config_parser *parser,
err:
while (i--) {
- size = CONFIG_TO_MBSIZE(config->ns_iommu_mappings[i]);
- daddr = config->ns_iommu_mappings[i] & ADDR_MASK;
+ size = gcip_ns_config_to_size(config->ns_iommu_mappings[i]);
+ daddr = config->ns_iommu_mappings[i] & GCIP_IMG_CFG_ADDR_MASK;
parser->ops->unmap(parser->data, daddr, size, 0);
}
return ret;
@@ -143,8 +121,8 @@ static void clear_ns_iommu_mappings(struct gcip_image_config_parser *parser,
int i;
for (i = config->num_ns_iommu_mappings - 1; i >= 0; i--) {
- size = CONFIG_TO_MBSIZE(config->ns_iommu_mappings[i]);
- daddr = config->ns_iommu_mappings[i] & ADDR_MASK;
+ size = gcip_ns_config_to_size(config->ns_iommu_mappings[i]);
+ daddr = config->ns_iommu_mappings[i] & GCIP_IMG_CFG_ADDR_MASK;
dev_dbg(parser->dev, "Image config removing NS IOMMU mapping: %pad size=%#lx",
&daddr, size);
parser->ops->unmap(parser->data, daddr, size, 0);