When a VCMDQ is allocated and VINTF page0 has been mmap'ed from the
kernel, access the VCMDQ registers directly through the VINTF page0
backing instead of using QEMU's cached register state.
VINTF page0 provides the backing memory region for VCMDQ registers
once a hardware queue is created. In that case, reads and writes
should reflect the live backing state.
If a VCMDQ is not allocated, or if VINTF page0 is not available,
continue to use the cached register values maintained by QEMU.
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
hw/arm/tegra241-cmdqv.c | 47 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c
index 002dde50fc..17b9552906 100644
--- a/hw/arm/tegra241-cmdqv.c
+++ b/hw/arm/tegra241-cmdqv.c
@@ -14,17 +14,44 @@
#include "smmuv3-accel.h"
#include "tegra241-cmdqv.h"
+static inline uint32_t *tegra241_cmdqv_vintf_ptr(Tegra241CMDQV *cmdqv,
+ int index, hwaddr offset0)
+{
+ if (!cmdqv->vcmdq[index] || !cmdqv->vintf_page0) {
+ return NULL;
+ }
+
+ return (uint32_t *)(cmdqv->vintf_page0 + (index * 0x80) +
+ (offset0 - 0x10000));
+}
/*
* Read a VCMDQ register using VCMDQ0_* offsets.
*
* The caller normalizes the MMIO offset such that @offset0 always refers
* to a VCMDQ0_* register, while @index selects the VCMDQ instance.
*
- * All VCMDQ accesses return cached registers.
+ * If the VCMDQ is allocated and VINTF page0 is mmap'ed, read directly
+ * from the VINTF page0 backing. Otherwise, fall back to cached state.
*/
static uint64_t tegra241_cmdqv_read_vcmdq(Tegra241CMDQV *cmdqv, hwaddr offset0,
int index)
{
+ uint32_t *ptr = tegra241_cmdqv_vintf_ptr(cmdqv, index, offset0);
+
+ if (ptr) {
+ switch (offset0) {
+ case A_VCMDQ0_CONS_INDX:
+ case A_VCMDQ0_PROD_INDX:
+ case A_VCMDQ0_CONFIG:
+ case A_VCMDQ0_STATUS:
+ case A_VCMDQ0_GERROR:
+ case A_VCMDQ0_GERRORN:
+ return *ptr;
+ default:
+ break;
+ }
+ }
+
switch (offset0) {
case A_VCMDQ0_CONS_INDX:
return cmdqv->vcmdq_cons_indx[index];
@@ -250,11 +277,29 @@ static bool tegra241_cmdqv_mmap_vintf_page0(Tegra241CMDQV *cmdqv, Error **errp)
*
* The caller normalizes the MMIO offset such that @offset0 always refers
* to a VCMDQ0_* register, while @index selects the VCMDQ instance.
+ *
+ * If the VCMDQ is allocated and VINTF page0 is mmap'ed, write directly
+ * to the VINTF page0 backing. Otherwise, update cached state.
*/
static void
tegra241_cmdqv_write_vcmdq(Tegra241CMDQV *cmdqv, hwaddr offset0, int index,
uint64_t value, unsigned size, Error **errp)
{
+ uint32_t *ptr = tegra241_cmdqv_vintf_ptr(cmdqv, index, offset0);
+
+ if (ptr) {
+ switch (offset0) {
+ case A_VCMDQ0_CONS_INDX:
+ case A_VCMDQ0_PROD_INDX:
+ case A_VCMDQ0_CONFIG:
+ case A_VCMDQ0_GERRORN:
+ *ptr = (uint32_t)value;
+ return;
+ default:
+ break;
+ }
+ }
+
switch (offset0) {
case A_VCMDQ0_CONS_INDX:
cmdqv->vcmdq_cons_indx[index] = value;
--
2.43.0