@@ -816,8 +816,7 @@ static void guc_read_update_log_buffer(struct drm_device *dev)
if (!guc->log_obj)
return;
- log_buffer_state = src_ptr =
- kmap_atomic(i915_gem_object_get_page(guc->log_obj, 0));
+ log_buffer_state = src_ptr = guc->log_buf_addr;
/* Get the pointer to local buffer to store the logs */
dst_ptr = log_buffer_copy_state = guc_get_write_buffer(guc);
@@ -847,14 +846,11 @@ static void guc_read_update_log_buffer(struct drm_device *dev)
log_buffer_copy_state++;
}
- kunmap_atomic(src_ptr);
-
/* Now copy the actual logs */
for (i=1; (i < guc->log_obj->base.size / PAGE_SIZE) && dst_ptr; i++) {
dst_ptr += PAGE_SIZE;
- src_ptr = kmap_atomic(i915_gem_object_get_page(guc->log_obj, i));
+ src_ptr += PAGE_SIZE;
memcpy(dst_ptr, src_ptr, PAGE_SIZE);
- kunmap_atomic(src_ptr);
}
}
@@ -983,6 +979,7 @@ static void guc_create_log(struct intel_guc *guc)
struct drm_i915_gem_object *obj;
unsigned long offset;
uint32_t size, flags;
+ void *vaddr;
if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX)
i915.guc_log_level = GUC_LOG_VERBOSITY_MAX;
@@ -1003,6 +1000,21 @@ static void guc_create_log(struct intel_guc *guc)
}
guc->log_obj = obj;
+
+ /* Create a WC (Uncached for read) mapping so that we can
+ * directly get the data (up-to-date) from system memory.
+ */
+ vaddr = i915_gem_object_pin_map(obj, true);
+ if (IS_ERR(vaddr)) {
+ DRM_DEBUG_DRIVER("Couldn't map log buffer pages(%ld)\n",
+ PTR_ERR(vaddr));
+ i915.guc_log_level = -1;
+ gem_release_guc_obj(dev_priv->guc.log_obj);
+ guc->log_obj = NULL;
+ return;
+ }
+
+ guc->log_buf_addr = vaddr;
}
/* each allocated unit is a page */
@@ -1176,6 +1188,9 @@ void i915_guc_submission_fini(struct drm_device *dev)
gem_release_guc_obj(dev_priv->guc.ads_obj);
guc->ads_obj = NULL;
+ if (guc->log_obj)
+ i915_gem_object_unpin_map(guc->log_obj);
+ guc->log_buf_addr = NULL;
gem_release_guc_obj(dev_priv->guc.log_obj);
guc->log_obj = NULL;
guc_logging_fini(guc);
@@ -125,6 +125,7 @@ struct intel_guc {
struct intel_guc_fw guc_fw;
uint32_t log_flags;
struct drm_i915_gem_object *log_obj;
+ void *log_buf_addr;
struct rchan *log_relay_chan;
/*
* work, interrupts_enabled are protected by dev_priv->irq_lock