summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurora zuma automerger <aurora-zuma-automerger@google.com>2023-03-28 13:25:52 +0000
committerCopybara-Service <copybara-worker@google.com>2023-04-10 11:04:23 -0700
commit0f9718887f9f52c056812dc6e21a6451cc8f4b12 (patch)
tree8175e4e5f4a198d39c9a03ac20fab937c73ade02
parent2ddcce971c7d6a92830220df66b8b70abb621392 (diff)
downloadzuma-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--Makefile10
-rw-r--r--callisto-platform.c2
-rw-r--r--gcip-kernel-driver/drivers/gcip/gcip-kci.c2
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-kci.h1
-rw-r--r--gxp-common-platform.c18
-rw-r--r--gxp-debug-dump.c27
-rw-r--r--gxp-dma-iommu.c16
-rw-r--r--gxp-domain-pool.c4
-rw-r--r--gxp-firmware-data.c4
-rw-r--r--gxp-internal.h11
-rw-r--r--gxp-kci.c34
-rw-r--r--gxp-kci.h7
-rw-r--r--gxp-lpm.c2
-rw-r--r--gxp-mcu-firmware.c7
-rw-r--r--gxp-mcu-fs.c23
-rw-r--r--gxp-pm.c29
-rw-r--r--gxp-uci.c20
-rw-r--r--gxp-vd.c59
-rw-r--r--gxp-vd.h16
-rw-r--r--gxp.h19
20 files changed, 272 insertions, 39 deletions
diff --git a/Makefile b/Makefile
index 151a194..37b6e30 100644
--- a/Makefile
+++ b/Makefile
@@ -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 */
/*
diff --git a/gxp-kci.c b/gxp-kci.c
index 46636d4..e916080 100644
--- a/gxp-kci.c
+++ b/gxp-kci.c
@@ -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;
+}
diff --git a/gxp-kci.h b/gxp-kci.h
index cb5e23d..999a757 100644
--- a/gxp-kci.h
+++ b/gxp-kci.h
@@ -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__ */
diff --git a/gxp-lpm.c b/gxp-lpm.c
index 1e51b40..4897f48 100644
--- a/gxp-lpm.c
+++ b/gxp-lpm.c
@@ -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 */
}
diff --git a/gxp-pm.c b/gxp-pm.c
index 146e788..1cf0782 100644
--- a/gxp-pm.c
+++ b/gxp-pm.c
@@ -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)
/*
diff --git a/gxp-uci.c b/gxp-uci.c
index 1506e9a..430422b 100644
--- a/gxp-uci.c
+++ b/gxp-uci.c
@@ -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) {
diff --git a/gxp-vd.c b/gxp-vd.c
index 27a69a1..d6c5be8 100644
--- a/gxp-vd.c
+++ b/gxp-vd.c
@@ -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;
diff --git a/gxp-vd.h b/gxp-vd.h
index 150d664..be9a108 100644
--- a/gxp-vd.h
+++ b/gxp-vd.h
@@ -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
diff --git a/gxp.h b/gxp.h
index 3387089..44ce609 100644
--- a/gxp.h
+++ b/gxp.h
@@ -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__ */