From patchwork Sun Dec 14 03:08:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 5487121 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id DDE8DBEEA8 for ; Sun, 14 Dec 2014 03:08:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 31E4E20A0A for ; Sun, 14 Dec 2014 03:08:35 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 2F99020A0D for ; Sun, 14 Dec 2014 03:08:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A027A6E221; Sat, 13 Dec 2014 19:08:29 -0800 (PST) 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 EA7C26E0BB; Sat, 13 Dec 2014 19:08:27 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 13 Dec 2014 19:08:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,573,1413270000"; d="scan'208";a="647252537" Received: from unknown (HELO ironside.intel.com) ([10.255.13.249]) by fmsmga002.fm.intel.com with ESMTP; 13 Dec 2014 19:08:26 -0800 From: Ben Widawsky To: DRI Development Date: Sat, 13 Dec 2014 19:08:23 -0800 Message-Id: <1418526504-26316-4-git-send-email-benjamin.widawsky@intel.com> X-Mailer: git-send-email 2.1.3 In-Reply-To: <1418526504-26316-1-git-send-email-benjamin.widawsky@intel.com> References: <1418526504-26316-1-git-send-email-benjamin.widawsky@intel.com> Cc: Intel GFX , Ben Widawsky , Ben Widawsky Subject: [Intel-gfx] [PATCH 3/4] drm/cache: Return what type of cache flush occurred 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-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The caller of the cache flush APIs can sometimes do useful things with the information of how the cache was flushed. For instance, when giving buffers to the GPU to read, we need to make sure all of them have properly invalidated the caches (when not using LLC). If we can determine a wbinvd() occurred though, we can skip trying to clflush all remaining objects. There is a further optimization to be made here in the driver specific code where it can try to flush the largest object first in hopes of it needing a wbinvd(). I haven't implemented that yet. The enum parts of this were very minimally considered for the sake of getting the data for the profile. Cc: Intel GFX Signed-off-by: Ben Widawsky --- drivers/gpu/drm/drm_cache.c | 34 +++++++++++++++++++++++++--------- include/drm/drmP.h | 13 ++++++++++--- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index 6009c2d..433b15d 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -80,21 +80,25 @@ drm_cache_should_clflush(unsigned long num_pages) } #endif -void +int drm_clflush_pages(struct page *pages[], unsigned long num_pages) { #if defined(CONFIG_X86) if (cpu_has_clflush && drm_cache_should_clflush(num_pages)) { drm_cache_flush_clflush(pages, num_pages); - return; + return DRM_CACHE_FLUSH_CL; } - if (wbinvd_on_all_cpus()) + if (wbinvd_on_all_cpus()) { printk(KERN_ERR "Timed out waiting for cache flush.\n"); + return DRM_CACHE_FLUSH_ERROR; + } else + return DRM_CACHE_FLUSH_WBINVD; #elif defined(__powerpc__) unsigned long i; + int ret = DRM_CACHE_FLUSH_NONE; for (i = 0; i < num_pages; i++) { struct page *page = pages[i]; void *page_virtual; @@ -106,15 +110,19 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) flush_dcache_range((unsigned long)page_virtual, (unsigned long)page_virtual + PAGE_SIZE); kunmap_atomic(page_virtual); + ret = DRM_CACHE_FLUSH_DCACHE; } + WARN_ON(ret == DRM_CACHE_FLUSH_NONE); + return ret; #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); WARN_ON_ONCE(1); + return DRM_CACHE_FLUSH_NONE; #endif } EXPORT_SYMBOL(drm_clflush_pages); -void +int drm_clflush_sg(struct sg_table *st) { #if defined(CONFIG_X86) @@ -126,19 +134,23 @@ drm_clflush_sg(struct sg_table *st) drm_clflush_page(sg_page_iter_page(&sg_iter)); mb(); - return; + return DRM_CACHE_FLUSH_CL; } - if (wbinvd_on_all_cpus()) + if (wbinvd_on_all_cpus()) { printk(KERN_ERR "Timed out waiting for cache flush.\n"); + return DRM_CACHE_FLUSH_ERROR; + } else + return DRM_CACHE_FLUSH_WBINVD; #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); WARN_ON_ONCE(1); + return DRM_CACHE_FLUSH_NONE; #endif } EXPORT_SYMBOL(drm_clflush_sg); -void +int drm_clflush_virt_range(void *addr, unsigned long length) { #if defined(CONFIG_X86) @@ -149,14 +161,18 @@ drm_clflush_virt_range(void *addr, unsigned long length) clflushopt(addr); clflushopt(end - 1); mb(); - return; + return DRM_CACHE_FLUSH_CL; } - if (wbinvd_on_all_cpus()) + if (wbinvd_on_all_cpus()) { printk(KERN_ERR "Timed out waiting for cache flush.\n"); + return DRM_CACHE_FLUSH_ERROR; + } else + return DRM_CACHE_FLUSH_WBINVD; #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); WARN_ON_ONCE(1); + return DRM_CACHE_FLUSH_NONE; #endif } EXPORT_SYMBOL(drm_clflush_virt_range); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8ba35c6..09ebe46 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -884,9 +884,16 @@ int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv); /* Cache management (drm_cache.c) */ -void drm_clflush_pages(struct page *pages[], unsigned long num_pages); -void drm_clflush_sg(struct sg_table *st); -void drm_clflush_virt_range(void *addr, unsigned long length); +enum drm_cache_flush { + DRM_CACHE_FLUSH_NONE=0, + DRM_CACHE_FLUSH_ERROR, + DRM_CACHE_FLUSH_CL, + DRM_CACHE_FLUSH_WBINVD, + DRM_CACHE_FLUSH_DCACHE, +}; +int drm_clflush_pages(struct page *pages[], unsigned long num_pages); +int drm_clflush_sg(struct sg_table *st); +int drm_clflush_virt_range(void *addr, unsigned long length); /* * These are exported to drivers so that they can implement fencing using