drm/i915/gvt: Add mmio iterator intel_gvt_for_each_tracked_mmio()
authorChangbin Du <changbin.du@intel.com>
Mon, 23 Oct 2017 03:46:43 +0000 (11:46 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Thu, 16 Nov 2017 03:48:32 +0000 (11:48 +0800)
This patch add a function intel_gvt_for_each_tracked_mmio() to
iterate each tracked mmio. The caller don't be aware of how the
tracked mmios are presented internally.

v2: remove snapshot_hw_mmio_registers().

Signed-off-by: Changbin Du <changbin.du@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/firmware.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio.h

index a26c1705430eb2134d002b68ddcb26d272684bd9..a73e1d418c228f20ac29cbfc161132a8d54669ae 100644 (file)
@@ -66,20 +66,23 @@ static struct bin_attribute firmware_attr = {
        .mmap = NULL,
 };
 
-static int expose_firmware_sysfs(struct intel_gvt *gvt)
+static int mmio_snapshot_handler(struct intel_gvt *gvt, u32 offset, void *data)
 {
        struct drm_i915_private *dev_priv = gvt->dev_priv;
+
+       *(u32 *)(data + offset) = I915_READ_NOTRACE(_MMIO(offset));
+       return 0;
+}
+
+static int expose_firmware_sysfs(struct intel_gvt *gvt)
+{
        struct intel_gvt_device_info *info = &gvt->device_info;
        struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
-       struct intel_gvt_mmio_info *e;
-       struct gvt_mmio_block *block = gvt->mmio.mmio_block;
-       int num = gvt->mmio.num_mmio_block;
        struct gvt_firmware_header *h;
        void *firmware;
        void *p;
        unsigned long size, crc32_start;
-       int i, j;
-       int ret;
+       int i, ret;
 
        size = sizeof(*h) + info->mmio_size + info->cfg_space_size;
        firmware = vzalloc(size);
@@ -104,15 +107,8 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
 
        p = firmware + h->mmio_offset;
 
-       hash_for_each(gvt->mmio.mmio_info_table, i, e, node)
-               *(u32 *)(p + e->offset) = I915_READ_NOTRACE(_MMIO(e->offset));
-
-       for (i = 0; i < num; i++, block++) {
-               for (j = 0; j < block->size; j += 4)
-                       *(u32 *)(p + INTEL_GVT_MMIO_OFFSET(block->offset) + j) =
-                               I915_READ_NOTRACE(_MMIO(INTEL_GVT_MMIO_OFFSET(
-                                                       block->offset) + j));
-       }
+       /* Take a snapshot of hw mmio registers. */
+       intel_gvt_for_each_tracked_mmio(gvt, mmio_snapshot_handler, p);
 
        memcpy(gvt->firmware.mmio, p, info->mmio_size);
 
index 56ee588377f481be2bd7200f168a3e2304115bed..4f8d470dbb3fa5fe0200b9cacfc431b8cb499e06 100644 (file)
@@ -2971,6 +2971,40 @@ err:
        return ret;
 }
 
+/**
+ * intel_gvt_for_each_tracked_mmio - iterate each tracked mmio
+ * @gvt: a GVT device
+ * @handler: the handler
+ * @data: private data given to handler
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt,
+       int (*handler)(struct intel_gvt *gvt, u32 offset, void *data),
+       void *data)
+{
+       struct gvt_mmio_block *block = gvt->mmio.mmio_block;
+       struct intel_gvt_mmio_info *e;
+       int i, j, ret;
+
+       hash_for_each(gvt->mmio.mmio_info_table, i, e, node) {
+               ret = handler(gvt, e->offset, data);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < gvt->mmio.num_mmio_block; i++, block++) {
+               for (j = 0; j < block->size; j += 4) {
+                       ret = handler(gvt,
+                               INTEL_GVT_MMIO_OFFSET(block->offset) + j,
+                               data);
+                       if (ret)
+                               return ret;
+               }
+       }
+       return 0;
+}
 
 /**
  * intel_vgpu_default_mmio_read - default MMIO read handler
index dbc04ad2c7a1e0703f56fc8dbc515fc22b792abd..62709ac351cdcd713b7160c4c323a0fb0aff1aed 100644 (file)
@@ -72,6 +72,10 @@ bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device);
 
 int intel_gvt_setup_mmio_info(struct intel_gvt *gvt);
 void intel_gvt_clean_mmio_info(struct intel_gvt *gvt);
+int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt,
+       int (*handler)(struct intel_gvt *gvt, u32 offset, void *data),
+       void *data);
+
 
 #define INTEL_GVT_MMIO_OFFSET(reg) ({ \
        typeof(reg) __reg = reg; \