From patchwork Sat Jul 2 18:51:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: akash.goel@intel.com X-Patchwork-Id: 9211003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CC68460571 for ; Sat, 2 Jul 2016 18:38:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BD96E283F6 for ; Sat, 2 Jul 2016 18:38:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B265B28544; Sat, 2 Jul 2016 18:38:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23EE3283F6 for ; Sat, 2 Jul 2016 18:38:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9CD116E29B; Sat, 2 Jul 2016 18:38:42 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 1952D6E29B for ; Sat, 2 Jul 2016 18:38:40 +0000 (UTC) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 02 Jul 2016 11:38:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.26,564,1459839600"; d="scan'208"; a="1014206544" Received: from akashgoe-desktop.iind.intel.com ([10.223.82.36]) by fmsmga002.fm.intel.com with ESMTP; 02 Jul 2016 11:38:38 -0700 From: akash.goel@intel.com To: intel-gfx@lists.freedesktop.org Date: Sun, 3 Jul 2016 00:21:31 +0530 Message-Id: <1467485491-17247-15-git-send-email-akash.goel@intel.com> X-Mailer: git-send-email 1.9.2 In-Reply-To: <1467485491-17247-1-git-send-email-akash.goel@intel.com> References: <1467485491-17247-1-git-send-email-akash.goel@intel.com> Cc: Akash Goel Subject: [Intel-gfx] [PATCH 14/14] drm/i915: Optimization to reduce the sampling time of GuC log buffer X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Akash Goel GuC firmware sends an interrupt to flush the log buffer when it becomes half full, so Driver doesn't really need to sample the complete buffer and can just copy only the newly written data by GuC into the local buffer, i.e. as per the read & write pointer values. Moreover the flush interrupt would generally come for one type of log buffer, when it becomes half full, so at that time the other 2 types of log buffer would comparatively have much lesser unread data in them. In case of overflow reported by GuC, Driver do need to copy the entire buffer as the whole buffer would contain the unread data. Signed-off-by: Akash Goel --- drivers/gpu/drm/i915/i915_guc_submission.c | 68 +++++++++++++++++++++--------- drivers/gpu/drm/i915/i915_irq.c | 3 +- drivers/gpu/drm/i915/intel_guc.h | 2 +- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 2a192d4..9514645 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -866,32 +866,35 @@ static void* guc_get_write_buffer(struct intel_guc *guc) return relay_reserve(guc->log.relay_chan, guc->log.obj->base.size); } -static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all) +static void guc_read_update_log_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc *guc = &dev_priv->guc; struct guc_log_buffer_state *log_buffer_state; struct guc_log_buffer_state *log_buffer_copy_state; void *src_ptr, *dst_ptr; - u32 num_pages_to_copy; - int i; + bool new_overflow; + u32 i, buffer_size, read_offset, write_offset, bytes_to_copy; if (!guc->log.obj || !guc->log.buf_addr) return; - num_pages_to_copy = guc->log.obj->base.size / PAGE_SIZE; - /* Don't really need to copy crash buffer area in regular cases as there - * won't be any unread data there. - */ - if (!capture_all) - num_pages_to_copy -= (GUC_LOG_CRASH_PAGES + 1); - 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); + /* Actual logs are present from the 2nd page */ + src_ptr += PAGE_SIZE; + dst_ptr += PAGE_SIZE; + for (i = 0; i < GUC_MAX_LOG_BUFFER; i++) { + buffer_size = log_buffer_state->size; + read_offset = log_buffer_state->read_ptr; + write_offset = log_buffer_state->sampled_write_ptr; + new_overflow = 0; + + /* First copy the state structure */ if (log_buffer_copy_state) { memcpy(log_buffer_copy_state, log_buffer_state, sizeof(struct guc_log_buffer_state)); @@ -907,6 +910,10 @@ static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all) log_buffer_copy_state++; } + if (log_buffer_state->buffer_full_cnt != + guc->log.overflow_count[i]) + new_overflow = 1; + guc->log.overflow_count[i] = log_buffer_state->buffer_full_cnt; guc->log.flush_count[i] += log_buffer_state->flush_to_file; @@ -917,13 +924,36 @@ static void guc_read_update_log_buffer(struct drm_device *dev, bool capture_all) /* Clear the 'flush to file' flag */ log_buffer_state->flush_to_file = 0; log_buffer_state++; - } - /* Now copy the actual logs */ - for (i=1; (i < num_pages_to_copy) && dst_ptr; i++) { - dst_ptr += PAGE_SIZE; - src_ptr += PAGE_SIZE; - memcpy(dst_ptr, src_ptr, PAGE_SIZE); + if (!log_buffer_copy_state) + continue; + + /* Now copy the actual logs */ + if ((read_offset > buffer_size) || (write_offset > buffer_size)) { + DRM_ERROR("invalid log buffer state\n"); + /* copy the whole buffer, as offsets are unreliable */ + memcpy(dst_ptr, src_ptr, buffer_size); + } else if (new_overflow) { + /* Need to copy the whole buffer in case of overflow */ + memcpy(dst_ptr, src_ptr, buffer_size); + } else { + /* Just copy the new data */ + if (read_offset <= write_offset) { + bytes_to_copy = write_offset - read_offset; + memcpy(dst_ptr + read_offset, + src_ptr + read_offset, bytes_to_copy); + } else { + bytes_to_copy = buffer_size - read_offset; + memcpy(dst_ptr + read_offset, + src_ptr + read_offset, bytes_to_copy); + + bytes_to_copy = write_offset; + memcpy(dst_ptr, src_ptr, bytes_to_copy); + } + } + + src_ptr += buffer_size; + dst_ptr += buffer_size; } } @@ -1370,11 +1400,11 @@ int intel_guc_resume(struct drm_device *dev) return host2guc_action(guc, data, ARRAY_SIZE(data)); } -void i915_guc_capture_logs(struct drm_device *dev, bool capture_all) +void i915_guc_capture_logs(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - guc_read_update_log_buffer(dev, capture_all); + guc_read_update_log_buffer(dev); host2guc_logbuffer_flush_complete(&dev_priv->guc); } @@ -1395,7 +1425,7 @@ void i915_guc_capture_logs_on_reset(struct drm_device *dev) host2guc_force_logbuffer_flush(&dev_priv->guc); /* GuC would have updated the log buffer by now, so capture it */ - i915_guc_capture_logs(dev, true); + i915_guc_capture_logs(dev); end: mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e2cbe1e..99af3b5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1255,8 +1255,7 @@ static void gen9_guc2host_events_work(struct work_struct *work) msg = I915_READ(SOFT_SCRATCH(15)); if (msg & (GUC2HOST_MSG_CRASH_DUMP_POSTED | GUC2HOST_MSG_FLUSH_LOG_BUFFER)) { - i915_guc_capture_logs(dev_priv->dev, - msg & GUC2HOST_MSG_CRASH_DUMP_POSTED); + i915_guc_capture_logs(dev_priv->dev); /* Clear GuC to Host msg bits that are handled */ if (msg & GUC2HOST_MSG_FLUSH_LOG_BUFFER) diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index bd299d3..d9f50be 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -182,7 +182,7 @@ int i915_guc_wq_check_space(struct drm_i915_gem_request *rq); int i915_guc_submit(struct drm_i915_gem_request *rq); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); -void i915_guc_capture_logs(struct drm_device *dev, bool capture_all); +void i915_guc_capture_logs(struct drm_device *dev); void i915_guc_capture_logs_on_reset(struct drm_device *dev); void i915_guc_register(struct drm_device *dev); void i915_guc_unregister(struct drm_device *dev);