From: akash.goel@intel.com
To: intel-gfx@lists.freedesktop.org
Cc: sourab.gupta@intel.com, Akash Goel <akash.goel@intel.com>
Subject: [RFC 10/12] drm/i915: Support to capture GuC logs by multiple clients via device file iface
Date: Sat, 28 May 2016 01:13:01 +0530 [thread overview]
Message-ID: <1464378183-9433-11-git-send-email-akash.goel@intel.com> (raw)
In-Reply-To: <1464378183-9433-1-git-send-email-akash.goel@intel.com>
From: Akash Goel <akash.goel@intel.com>
This patch adds support for multiple clients to capture GuC logs via
'/dev/dri/guc_log' interface at the same time.
The implementation is done on the lines of '/dev/kmsg', so provides a
streaming behavior, on issuing the 'cat' command User will enter into a
read loop and will have to do 'CTRL+C' type action to come out of the loop.
Signed-off-by: Akash Goel <akash.goel@intel.com>
---
drivers/gpu/drm/i915/i915_guc_submission.c | 124 ++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_guc.h | 9 +++
2 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 8a79b6d..f20e352 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -988,11 +988,40 @@ static void guc_create_log_relay_file(struct intel_guc *guc)
static ssize_t guc_log_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
- return 0;
+ struct intel_guc_log_client *log_client = file->private_data;
+ struct intel_guc *guc;
+ ssize_t ret;
+
+ if (!log_client)
+ return -EBADF;
+
+ guc = log_client->guc;
+
+ /* Can't provide more than scratch buf size */
+ len = min(PAGE_SIZE, len);
+
+ spin_lock_irq(&guc->log.buf_lock);
+ ret = i915_guc_read_logs(log_client, len, file->f_flags);
+ spin_unlock_irq(&guc->log.buf_lock);
+
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user(buf, log_client->scratch_buf, ret))
+ return -EFAULT;
+
+ return ret;
}
static int guc_log_release(struct inode *inode, struct file *file)
{
+ struct intel_guc_log_client *log_client = file->private_data;
+
+ if (!log_client)
+ return 0;
+
+ kfree(log_client->scratch_buf);
+ kfree(log_client);
return 0;
}
@@ -1003,6 +1032,26 @@ static int guc_log_open(struct inode *inode, struct file *file)
container_of(miscdev, struct intel_guc_log, misc_dev);
struct intel_guc *guc =
container_of(guc_log, struct intel_guc, log);
+ struct intel_guc_log_client *log_client;
+
+ log_client = kzalloc(sizeof(struct intel_guc_log_client), GFP_KERNEL);
+ if (!log_client)
+ return -ENOMEM;
+
+ /* TODO, decide apt size for scratch_buf (and allocate as a GEM obj) */
+ log_client->scratch_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!log_client->scratch_buf) {
+ kfree(log_client);
+ return -ENOMEM;
+ }
+
+ log_client->guc = guc;
+
+ spin_lock(&guc->log.buf_lock);
+ log_client->read_seq = guc->log.first_seq;
+ spin_unlock(&guc->log.buf_lock);
+
+ file->private_data = log_client;
return 0;
}
@@ -1365,3 +1414,76 @@ void i915_guc_capture_logs(struct drm_device *dev)
if (host2guc_action(guc, data, 1))
DRM_ERROR("Failed\n");
}
+
+ssize_t i915_guc_read_logs(struct intel_guc_log_client *log_client,
+ size_t count, uint32_t f_flags)
+{
+ struct intel_guc *guc = log_client->guc;
+ char *buf = log_client->scratch_buf;
+ void *log_buf_base, *log_buf_end, *log_buf_read, *log_buf_write;
+ uint32_t read_index, next_index;
+ size_t n_subbufs, subbuf_size;
+ ssize_t ret_count = 0;
+ int ret = 0;
+
+ assert_spin_locked(&guc->log.buf_lock);
+
+ subbuf_size = guc->log_obj->base.size;
+ n_subbufs = guc->log.buf_obj->base.size / subbuf_size;
+
+ /* Wait if there is no data to read */
+ while (log_client->read_seq == guc->log.next_seq) {
+ if (f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ ret = wait_event_interruptible_lock_irq(guc->log.wq,
+ log_client->read_seq != guc->log.next_seq,
+ guc->log.buf_lock);
+ if (ret)
+ return ret;
+ }
+
+ /* Check if our last seen data is gone */
+ if (log_client->read_seq < guc->log.first_seq) {
+ log_client->read_seq = guc->log.first_seq;
+ log_client->read_offset = 0;
+ }
+
+ read_index = log_client->read_seq & (n_subbufs - 1);
+ next_index = guc->log.next_seq & (n_subbufs - 1);
+
+ log_buf_base = guc->log.buf_obj->mapping;
+ log_buf_end = log_buf_base + guc->log.buf_obj->base.size;
+ log_buf_write = log_buf_base + next_index * subbuf_size;
+ log_buf_read = log_buf_base + read_index * subbuf_size +
+ log_client->read_offset;
+
+ if (log_buf_read < log_buf_write) {
+ ret_count =
+ min_t(size_t, count, (log_buf_write - log_buf_read));
+ memcpy(buf, log_buf_read, ret_count);
+ } else {
+ ssize_t ret_count1, ret_count2 = 0;
+ ret_count1 =
+ min_t(size_t, count, (log_buf_end - log_buf_read));
+ memcpy(buf, log_buf_read, ret_count1);
+ if (count > ret_count1) {
+ count -= ret_count1;
+ buf += ret_count1;
+ ret_count2 =
+ min_t(size_t, count, (log_buf_write - log_buf_base));
+ memcpy(buf, log_buf_base, ret_count2);
+ }
+ ret_count = ret_count1 + ret_count2;
+ }
+
+ log_client->read_offset += ret_count;
+ if (log_client->read_offset >= subbuf_size) {
+ log_client->read_seq += log_client->read_offset / subbuf_size;
+ log_client->read_offset %= subbuf_size;
+ }
+
+ WARN_ON(log_client->read_seq > guc->log.next_seq);
+
+ return ret_count;
+}
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 13810d0..985fb4b 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -121,6 +121,13 @@ struct intel_guc_fw {
uint32_t ucode_offset;
};
+struct intel_guc_log_client {
+ uint64_t read_seq;
+ uint32_t read_offset;
+ char *scratch_buf;
+ struct intel_guc *guc;
+};
+
struct intel_guc_log {
struct drm_i915_gem_object *buf_obj;
spinlock_t buf_lock;
@@ -180,5 +187,7 @@ int i915_guc_submit(struct drm_i915_gem_request *rq);
void i915_guc_submission_disable(struct drm_device *dev);
void i915_guc_submission_fini(struct drm_device *dev);
void i915_guc_capture_logs(struct drm_device *dev);
+ssize_t i915_guc_read_logs(struct intel_guc_log_client *log_client,
+ size_t count, uint32_t f_flags);
#endif
--
1.9.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2016-05-27 19:30 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-27 19:42 [RFC 00/12] Support for sustained capturing of GuC firmware logs akash.goel
2016-05-27 19:42 ` [RFC 01/12] drm/i915: Decouple GuC log setup from verbosity parameter akash.goel
2016-05-27 19:42 ` [RFC 02/12] drm/i915: Add GuC ukernel logging related fields to fw interface file akash.goel
2016-05-27 19:42 ` [RFC 03/12] drm/i915: Support for GuC interrupts akash.goel
2016-05-27 19:43 ` Chris Wilson
2016-05-28 8:46 ` Goel, Akash
2016-05-27 19:56 ` Chris Wilson
2016-05-28 9:22 ` Goel, Akash
2016-05-28 12:13 ` Chris Wilson
2016-05-28 13:45 ` Goel, Akash
2016-05-28 14:35 ` Chris Wilson
2016-05-28 17:33 ` Goel, Akash
2016-05-27 19:42 ` [RFC 04/12] drm/i915: Handle log buffer flush interrupt event from GuC akash.goel
2016-05-27 19:42 ` [RFC 05/12] drm/i915: Add a relay backed debugfs interface for capturing GuC logs akash.goel
2016-05-27 19:42 ` [RFC 06/12] drm/i915: Store GuC ukernel logs in the relay buffer akash.goel
2016-05-27 19:42 ` [RFC 07/12] drm/i915: Allocate local buffer to store GuC ukernel logs akash.goel
2016-05-27 19:42 ` [RFC 08/12] drm/i915: Store GuC ukernel logs in the local buffer akash.goel
2016-05-27 19:43 ` [RFC 09/12] drm/i915: Add a char device file interface to capture GuC ukernel logs akash.goel
2016-05-27 19:48 ` Chris Wilson
2016-05-28 8:51 ` Goel, Akash
2016-05-27 19:43 ` akash.goel [this message]
2016-05-27 19:43 ` [RFC 11/12] drm/i915: Add sysfs interface to capture the " akash.goel
2016-05-27 19:43 ` [RFC 12/12] drm/i915: Forcefully flush GuC log buffer on reset akash.goel
2016-05-28 6:09 ` ✗ Ro.CI.BAT: failure for Support for sustained capturing of GuC firmware logs Patchwork
2016-06-02 10:16 ` [RFC 00/12] " Daniel Vetter
2016-06-02 10:21 ` Johannes Berg
2016-06-03 7:15 ` Daniel Vetter
2016-06-03 10:14 ` Goel, Akash
2016-06-03 10:20 ` Chris Wilson
2016-06-08 8:30 ` Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1464378183-9433-11-git-send-email-akash.goel@intel.com \
--to=akash.goel@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=sourab.gupta@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox