From patchwork Tue Jul 23 18:42:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 2832169 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 429899F4D4 for ; Tue, 23 Jul 2013 18:43:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 465BE201CD for ; Tue, 23 Jul 2013 18:43:39 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5B93D2018C for ; Tue, 23 Jul 2013 18:43:38 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 25367E65DA for ; Tue, 23 Jul 2013 11:43:38 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from oproxy13-pub.unifiedlayer.com (oproxy13-pub.unifiedlayer.com [69.89.16.30]) by gabe.freedesktop.org (Postfix) with SMTP id A0AA4E5EA4 for ; Tue, 23 Jul 2013 11:43:01 -0700 (PDT) Received: (qmail 5207 invoked by uid 0); 23 Jul 2013 18:42:59 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by oproxy13.unifiedlayer.com with SMTP; 23 Jul 2013 18:42:59 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuousgeek.org; s=default; h=Message-Id:Date:Subject:To:From; bh=4rwZwE+luUk/Y8gHB4hOZvWkaWjRRmHjev3/xpkWlbk=; b=PUfjczJwkKmn0tUhAcMyUK7RPuMmz2CKpi4JXXx4Kg25k0B/4A/jZ0hmE4UU+tMJkHoTjzHHD6RCMWZ7jXB9koAhHta9Ty4ik6qvbprYLAJT+VMrKL1U2I0siPMHIVo5; Received: from [67.161.37.189] (port=59055 helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:CAMELLIA256-SHA:256) (Exim 4.80) (envelope-from ) id 1V1hY3-0005ci-3L for intel-gfx@lists.freedesktop.org; Tue, 23 Jul 2013 12:42:59 -0600 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Tue, 23 Jul 2013 11:42:57 -0700 Message-Id: <1374604978-3195-1-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.7.9.5 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.161.37.189 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH 1/2] resource: add devm_request_mem_region_ram() for reserving RAM regions X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham 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 Early x86 code reserves a buffer called "RAM buffer" to prevent MMIO reservations from landing on top of potential RAM space, which can fail due to decode priority in the chipset. However, some drivers need to reserve RAM regions that may overlap the padding, and may not be described in the E820 map (like the i915 driver). So add a new entry point to allow this, that will shrink the "RAM buffer" padding if needed. Signed-off-by: Jesse Barnes --- include/linux/ioport.h | 6 ++++ kernel/resource.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 89b7c24..f44a4ad 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -209,11 +209,17 @@ struct device; __devm_request_region(dev, &ioport_resource, (start), (n), (name)) #define devm_request_mem_region(dev,start,n,name) \ __devm_request_region(dev, &iomem_resource, (start), (n), (name)) +#define devm_request_mem_region_ram(dev,start,n,name) \ + __devm_request_region_ram(dev, &iomem_resource, (start), (n), (name)) extern struct resource * __devm_request_region(struct device *dev, struct resource *parent, resource_size_t start, resource_size_t n, const char *name); +extern struct resource * __devm_request_region_ram(struct device *dev, + struct resource *parent, resource_size_t start, + resource_size_t n, const char *name); + #define devm_release_region(dev, start, n) \ __devm_release_region(dev, &ioport_resource, (start), (n)) #define devm_release_mem_region(dev, start, n) \ diff --git a/kernel/resource.c b/kernel/resource.c index 3f285dc..d8f8783 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1216,6 +1216,81 @@ struct resource * __devm_request_region(struct device *dev, } EXPORT_SYMBOL(__devm_request_region); +/* Same as above, but conflicts with "RAM buffer" are ok */ +struct resource * __devm_request_region_ram(struct device *dev, + struct resource *parent, resource_size_t start, + resource_size_t n, const char *name) +{ + struct region_devres *dr = NULL; + struct resource *res; + + dr = devres_alloc(devm_region_release, sizeof(struct region_devres), + GFP_KERNEL); + if (!dr) + return NULL; + + dr->parent = parent; + dr->start = start; + dr->n = n; + + res = __request_region(parent, start, n, name, 0); + if (res) { + goto out; + } else { + struct resource *conflict; + + res = alloc_resource(GFP_ATOMIC); + if (!res) + goto fail; + + res->name = name; + res->start = start; + res->end = start + n; + res->flags = IORESOURCE_BUSY; + + conflict = request_resource_conflict(parent, res); + if (!conflict) + goto out; + + if (strcmp(conflict->name, "RAM buffer")) + goto fail_free; + + if (conflict->start <= res->start && + conflict->end <= res->end) { + resource_size_t new_size; + + new_size = res->start - conflict->start; + adjust_resource(conflict, conflict->start, new_size); + } else if (conflict->start >= res->start && + conflict->end >= res->end) { + resource_size_t new_size; + + new_size = conflict->end - res->end; + adjust_resource(conflict, res->start, new_size); + } + + conflict = request_resource_conflict(parent, res); + if (!conflict) + goto out; + else { + dev_err("failed to adjust RAM buffer for %s\n", + res->name); + goto fail_free; + } + } + +out: + devres_add(dev, dr); + return res; + +fail_free: + free_resource(res); +fail: + devres_free(dr); + return res; +} +EXPORT_SYMBOL(__devm_request_region_ram); + void __devm_release_region(struct device *dev, struct resource *parent, resource_size_t start, resource_size_t n) {