[PATCH v3 4/7] drm/i915/guc: use iosys_map abstraction to access GuC log

Balasubramani Vivekanandan balasubramani.vivekanandan at intel.com
Tue Apr 26 16:51:45 UTC 2022


Pointer to the GuC log may be pointing to system memory or device memory
based on if the GuC log is backed by system memory or GPU local memory.
If the GuC log is on the local memory, we need to use memcpy_[from/to]io
APIs to access the logs to support i915 on non-x86 architectures.
iosys_map family of APIs provide the needed abstraction to access such
address pointers. There is parallel work ongoing to move all such memory
access in i915 to iosys_map APIs. Pointer to GuC log ported to iosys_map
in this patch as it provides a good base when changing to
drm_memcpy_from_wc.

Cc: Lucas De Marchi <lucas.demarchi at intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>

Signed-off-by: Balasubramani Vivekanandan <balasubramani.vivekanandan at intel.com>
---
 drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h |  2 +-
 .../gpu/drm/i915/gt/uc/intel_guc_capture.c    | 52 +++++++++----
 drivers/gpu/drm/i915/gt/uc/intel_guc_log.c    | 77 ++++++++++++++-----
 drivers/gpu/drm/i915/gt/uc/intel_guc_log.h    |  3 +-
 4 files changed, 98 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
index 3624abfd22d1..47bed2a0c409 100644
--- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
@@ -21,7 +21,7 @@ struct file;
  */
 struct __guc_capture_bufstate {
 	u32 size;
-	void *data;
+	struct iosys_map *data_map;
 	u32 rd;
 	u32 wr;
 };
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
index c4e25966d3e9..c4f7a28956b8 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
@@ -5,6 +5,7 @@
 
 #include <linux/types.h>
 
+#include <drm/drm_cache.h>
 #include <drm/drm_print.h>
 
 #include "gt/intel_engine_regs.h"
@@ -826,7 +827,6 @@ guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *
 	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
 	int tries = 2;
 	int avail = 0;
-	u32 *src_data;
 
 	if (!guc_capture_buf_cnt(buf))
 		return 0;
@@ -834,8 +834,7 @@ guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *
 	while (tries--) {
 		avail = guc_capture_buf_cnt_to_end(buf);
 		if (avail >= sizeof(u32)) {
-			src_data = (u32 *)(buf->data + buf->rd);
-			*dw = *src_data;
+			*dw = iosys_map_rd(buf->data_map, buf->rd, u32);
 			buf->rd += 4;
 			return 4;
 		}
@@ -852,7 +851,7 @@ guc_capture_data_extracted(struct __guc_capture_bufstate *b,
 			   int size, void *dest)
 {
 	if (guc_capture_buf_cnt_to_end(b) >= size) {
-		memcpy(dest, (b->data + b->rd), size);
+		drm_memcpy_from_wc_vaddr(dest, b->data_map, b->rd, size);
 		b->rd += size;
 		return true;
 	}
@@ -1343,22 +1342,24 @@ static void __guc_capture_process_output(struct intel_guc *guc)
 	struct intel_uc *uc = container_of(guc, typeof(*uc), guc);
 	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
 	struct guc_log_buffer_state log_buf_state_local;
-	struct guc_log_buffer_state *log_buf_state;
+	unsigned int capture_offset;
 	struct __guc_capture_bufstate buf;
-	void *src_data = NULL;
+	struct iosys_map src_map;
 	bool new_overflow;
 	int ret;
 
-	log_buf_state = guc->log.buf_addr +
-			(sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER);
-	src_data = guc->log.buf_addr + intel_guc_get_log_buffer_offset(GUC_CAPTURE_LOG_BUFFER);
+	src_map = IOSYS_MAP_INIT_OFFSET(&guc->log.buf_map,
+					intel_guc_get_log_buffer_offset(GUC_CAPTURE_LOG_BUFFER));
 
 	/*
 	 * Make a copy of the state structure, inside GuC log buffer
 	 * (which is uncached mapped), on the stack to avoid reading
 	 * from it multiple times.
 	 */
-	memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state));
+	capture_offset = sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER;
+	drm_memcpy_from_wc_vaddr(&log_buf_state_local, &guc->log.buf_map,
+				 capture_offset,
+				 sizeof(struct guc_log_buffer_state));
 	buffer_size = intel_guc_get_log_buffer_size(GUC_CAPTURE_LOG_BUFFER);
 	read_offset = log_buf_state_local.read_ptr;
 	write_offset = log_buf_state_local.sampled_write_ptr;
@@ -1385,7 +1386,7 @@ static void __guc_capture_process_output(struct intel_guc *guc)
 	buf.size = buffer_size;
 	buf.rd = read_offset;
 	buf.wr = write_offset;
-	buf.data = src_data;
+	buf.data_map = &src_map;
 
 	if (!uc->reset_in_progress) {
 		do {
@@ -1394,8 +1395,33 @@ static void __guc_capture_process_output(struct intel_guc *guc)
 	}
 
 	/* Update the state of log buffer err-cap state */
-	log_buf_state->read_ptr = write_offset;
-	log_buf_state->flush_to_file = 0;
+	iosys_map_wr_field(&guc->log.buf_map, capture_offset,
+			   struct guc_log_buffer_state, read_ptr, write_offset);
+
+	/* flush_to_file is a bitfield. iosys_map_wr_field cannot be used to
+	 * update bitfield member types. We make use of another member variable
+	 * `flags` which is a union of flush_to_file as following, to update
+	 * the flush_to_file bitfield.
+	 *
+	 * ====================================================================
+	 *	union {
+	 *		struct {
+	 *			u32 flush_to_file:1;
+	 *			u32 buffer_full_cnt:4;
+	 *			u32 reserved:27;
+	 *		};
+	 *		u32 flags;
+	 *	};
+	 * ====================================================================
+	 */
+	log_buf_state_local.flags = iosys_map_rd_field(&guc->log.buf_map,
+						       capture_offset,
+						       struct guc_log_buffer_state,
+						       flags);
+	log_buf_state_local.flush_to_file = 0;
+	iosys_map_wr_field(&guc->log.buf_map, capture_offset,
+			   struct guc_log_buffer_state, flags,
+			   log_buf_state_local.flags);
 	__guc_capture_flushlog_complete(guc);
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
index 78d2989fe917..62b917fbe731 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
@@ -3,6 +3,7 @@
  * Copyright © 2014-2019 Intel Corporation
  */
 
+#include <drm/drm_cache.h>
 #include <linux/debugfs.h>
 #include <linux/string_helpers.h>
 
@@ -217,11 +218,13 @@ size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type)
 static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log)
 {
 	unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt;
-	struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state;
+	struct guc_log_buffer_state *log_buf_snapshot_state;
 	struct guc_log_buffer_state log_buf_state_local;
 	enum guc_log_buffer_type type;
-	void *src_data, *dst_data;
+	void *dst_data;
 	bool new_overflow;
+	struct iosys_map src_data;
+	unsigned int type_offset;
 
 	mutex_lock(&log->relay.lock);
 
@@ -229,8 +232,7 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log)
 		goto out_unlock;
 
 	/* Get the pointer to shared GuC log buffer */
-	src_data = log->buf_addr;
-	log_buf_state = src_data;
+	src_data = log->buf_map;
 
 	/* Get the pointer to local buffer to store the logs */
 	log_buf_snapshot_state = dst_data = guc_get_write_buffer(log);
@@ -247,18 +249,22 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log)
 	}
 
 	/* Actual logs are present from the 2nd page */
-	src_data += PAGE_SIZE;
+	iosys_map_incr(&src_data, PAGE_SIZE);
 	dst_data += PAGE_SIZE;
 
 	/* For relay logging, we exclude error state capture */
-	for (type = GUC_DEBUG_LOG_BUFFER; type <= GUC_CRASH_DUMP_LOG_BUFFER; type++) {
+	for (type = GUC_DEBUG_LOG_BUFFER, type_offset = 0;
+	     type < GUC_CRASH_DUMP_LOG_BUFFER;
+	     type++, type_offset += sizeof(struct guc_log_buffer_state)) {
 		/*
 		 * Make a copy of the state structure, inside GuC log buffer
 		 * (which is uncached mapped), on the stack to avoid reading
 		 * from it multiple times.
 		 */
-		memcpy(&log_buf_state_local, log_buf_state,
-		       sizeof(struct guc_log_buffer_state));
+		iosys_map_memcpy_from(&log_buf_state_local, &log->buf_map,
+				      type_offset,
+				      sizeof(struct guc_log_buffer_state));
+
 		buffer_size = intel_guc_get_log_buffer_size(type);
 		read_offset = log_buf_state_local.read_ptr;
 		write_offset = log_buf_state_local.sampled_write_ptr;
@@ -268,15 +274,39 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log)
 		log->stats[type].flush += log_buf_state_local.flush_to_file;
 		new_overflow = intel_guc_check_log_buf_overflow(log, type, full_cnt);
 
-		/* Update the state of shared log buffer */
-		log_buf_state->read_ptr = write_offset;
-		log_buf_state->flush_to_file = 0;
-		log_buf_state++;
-
 		/* First copy the state structure in snapshot buffer */
 		memcpy(log_buf_snapshot_state, &log_buf_state_local,
 		       sizeof(struct guc_log_buffer_state));
 
+		/* Update the state of shared log buffer */
+		iosys_map_wr_field(&log->buf_map, type_offset,
+				   struct guc_log_buffer_state, read_ptr,
+				   write_offset);
+		/* flush_to_file is a bitfield. iosys_map_wr_field cannot be used to
+		 * update bitfield member types. We make use of another member variable
+		 * `flags` which is a union of flush_to_file as following, to update
+		 * the flush_to_file bitfield.
+		 *
+		 * ====================================================================
+		 *	union {
+		 *		struct {
+		 *			u32 flush_to_file:1;
+		 *			u32 buffer_full_cnt:4;
+		 *			u32 reserved:27;
+		 *		};
+		 *		u32 flags;
+		 *	};
+		 * ====================================================================
+		 */
+		log_buf_state_local.flags = iosys_map_rd_field(&log->buf_map,
+							       type_offset,
+							       struct guc_log_buffer_state,
+							       flags);
+		log_buf_state_local.flush_to_file = 0;
+		iosys_map_wr_field(&log->buf_map, type_offset,
+				   struct guc_log_buffer_state, flags,
+				   log_buf_state_local.flags);
+
 		/*
 		 * The write pointer could have been updated by GuC firmware,
 		 * after sending the flush interrupt to Host, for consistency
@@ -301,15 +331,16 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log)
 
 		/* Just copy the newly written data */
 		if (read_offset > write_offset) {
-			i915_memcpy_from_wc(dst_data, src_data, write_offset);
+			drm_memcpy_from_wc_vaddr(dst_data, &src_data, 0,
+						 write_offset);
 			bytes_to_copy = buffer_size - read_offset;
 		} else {
 			bytes_to_copy = write_offset - read_offset;
 		}
-		i915_memcpy_from_wc(dst_data + read_offset,
-				    src_data + read_offset, bytes_to_copy);
+		drm_memcpy_from_wc_vaddr(dst_data + read_offset, &src_data,
+					 read_offset, bytes_to_copy);
 
-		src_data += buffer_size;
+		iosys_map_incr(&src_data, buffer_size);
 		dst_data += buffer_size;
 	}
 
@@ -331,7 +362,7 @@ static int guc_log_relay_map(struct intel_guc_log *log)
 {
 	lockdep_assert_held(&log->relay.lock);
 
-	if (!log->vma || !log->buf_addr)
+	if (!log->vma || !iosys_map_is_null(&log->buf_map))
 		return -ENODEV;
 
 	/*
@@ -505,7 +536,11 @@ int intel_guc_log_create(struct intel_guc_log *log)
 		i915_vma_unpin_and_release(&log->vma, 0);
 		goto err;
 	}
-	log->buf_addr = vaddr;
+
+	if (i915_gem_object_is_lmem(log->vma->obj))
+		iosys_map_set_vaddr_iomem(&log->buf_map, (void __iomem *)vaddr);
+	else
+		iosys_map_set_vaddr(&log->buf_map, vaddr);
 
 	log->level = __get_default_log_level(log);
 	DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n",
@@ -522,7 +557,7 @@ int intel_guc_log_create(struct intel_guc_log *log)
 
 void intel_guc_log_destroy(struct intel_guc_log *log)
 {
-	log->buf_addr = NULL;
+	iosys_map_clear(&log->buf_map);
 	i915_vma_unpin_and_release(&log->vma, I915_VMA_RELEASE_MAP);
 }
 
@@ -568,7 +603,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 
 bool intel_guc_log_relay_created(const struct intel_guc_log *log)
 {
-	return log->buf_addr;
+	return !iosys_map_is_null(&log->buf_map);
 }
 
 int intel_guc_log_relay_open(struct intel_guc_log *log)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
index 18007e639be9..a66e882ba716 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
@@ -6,6 +6,7 @@
 #ifndef _INTEL_GUC_LOG_H_
 #define _INTEL_GUC_LOG_H_
 
+#include <linux/iosys-map.h>
 #include <linux/mutex.h>
 #include <linux/relay.h>
 #include <linux/workqueue.h>
@@ -49,7 +50,7 @@ struct intel_guc;
 struct intel_guc_log {
 	u32 level;
 	struct i915_vma *vma;
-	void *buf_addr;
+	struct iosys_map buf_map;
 	struct {
 		bool buf_in_use;
 		bool started;
-- 
2.25.1



More information about the dri-devel mailing list