@@ -874,7 +874,7 @@ static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all)
u32 num_pages_to_copy;
int i;
- if (!guc->log.obj)
+ if (!guc->log.obj || !guc->log.buf_addr)
return;
num_pages_to_copy = guc->log.obj->base.size / PAGE_SIZE;
@@ -884,8 +884,7 @@ static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all)
if (!capture_all)
num_pages_to_copy -= (GUC_LOG_CRASH_PAGES + 1);
- 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);
@@ -906,8 +905,6 @@ static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all)
log_buffer_copy_state++;
}
- /* FIXME: invalidate/flush for log buffer needed */
-
/* Update the read pointer in the shared log buffer */
log_buffer_state->read_ptr =
log_buffer_state->sampled_write_ptr;
@@ -917,14 +914,11 @@ static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all)
log_buffer_state++;
}
- kunmap_atomic(src_ptr);
-
/* Now copy the actual logs */
for (i=1; (i < num_pages_to_copy) && 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);
}
}
@@ -1016,7 +1010,7 @@ static int guc_create_log_relay_file(struct intel_guc *guc)
/* Keep the size of sub buffers same as shared log buffer */
subbuf_size = guc->log.obj->base.size;
- n_subbufs = i915.guc_log_buffer_nr
+ n_subbufs = i915.guc_log_buffer_nr;
guc_log_relay_chan = relay_open("guc_log", log_dir,
subbuf_size, n_subbufs, &relay_callbacks, dev);
@@ -1051,6 +1045,7 @@ static int guc_log_late_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
+ void *vaddr;
int ret;
lockdep_assert_held(&dev->struct_mutex);
@@ -1061,9 +1056,26 @@ static int guc_log_late_setup(struct drm_device *dev)
if (WARN_ON(guc->log.relay_chan))
return -EINVAL;
+ /* If log_level was set as -1 at boot time, then vmalloc mapping would
+ * not have been created for the log buffer, so create one now.
+ */
+ if (!guc->log.buf_addr) {
+ vaddr = i915_gem_object_pin_map(guc->log.obj, true);
+ if (IS_ERR(vaddr)) {
+ ret = PTR_ERR(vaddr);
+ DRM_DEBUG_DRIVER("Couldn't map log buffer %d\n", ret);
+ goto err;
+ }
+ guc->log.buf_addr = vaddr;
+ }
+
+
ret = guc_create_log_relay_file(guc);
- if (ret)
+ if (ret) {
+ guc->log.buf_addr = NULL;
+ i915_gem_object_unpin_map(guc->log.obj);
goto err;
+ }
return 0;
err:
@@ -1098,6 +1110,25 @@ static void guc_create_log(struct intel_guc *guc)
return;
}
+ if (i915.guc_log_level >= 0) {
+ /* Create a WC (Uncached for read) mapping so that we
+ * can directly get the data (up-to-date) from memory.
+ * Also create the mapping now only to properly handle
+ * the flush interrupts which can come before we create
+ * a relay channel at the end of Driver load.
+ */
+ void *vaddr = i915_gem_object_pin_map(obj, true);
+ if (IS_ERR(vaddr)) {
+ DRM_DEBUG_DRIVER("Couldn't map log buffer %ld\n",
+ PTR_ERR(vaddr));
+ gem_release_guc_obj(obj);
+ i915.guc_log_level = -1;
+ return;
+ }
+
+ guc->log.buf_addr = vaddr;
+ }
+
guc->log.obj = obj;
}
@@ -127,6 +127,7 @@ struct intel_guc_log {
struct drm_i915_gem_object *obj;
struct workqueue_struct *wq;
struct rchan *relay_chan;
+ void *buf_addr;
};
struct intel_guc {