From patchwork Wed Feb 13 15:10:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14779 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 67F5023EAD for ; Wed, 13 Feb 2013 15:10:53 +0000 (UTC) Received: from mail-vb0-f47.google.com (mail-vb0-f47.google.com [209.85.212.47]) by fiordland.canonical.com (Postfix) with ESMTP id EE1ADA1906C for ; Wed, 13 Feb 2013 15:10:52 +0000 (UTC) Received: by mail-vb0-f47.google.com with SMTP id e21so818186vbm.34 for ; Wed, 13 Feb 2013 07:10:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-extloop1:x-ironport-av:from:to:date:message-id :x-mailer:in-reply-to:references:cc:subject:x-beenthere :x-mailman-version:precedence:list-id:list-unsubscribe:list-archive :list-post:list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-gm-message-state; bh=SmTFFjjNafJQo1tJwfuEX1tkn7X0ASTFD8/DCxnpn38=; b=OFOQ8279qcn/d3wRYR2Mx3v6UgtQ+WTZzVjJexY5hZD0iSt6Of3cyYiH4UJcJ/8HQe aJRnsOLH0cIfeeaSeYESjO+rET6728rzY3t+/NB3rNo1G5AO264P/LumqQdlReAyuc7h CV+jG8yFrofgVpC15CtQkWq2LbdETwhJWNcTu99VfJ0XRpjdOmkXybZorcpcZB0BUG5T glcD6XhavfpeVc5cpaCUrKqPREwEgf9f2EhEAZABkKrbnFNk8dkVWEdFcmvJIq6Y48Us xMNOFkcGcx9b5tKnmamnYwR3tETysWmBkzRxf1fuS6PNJz+AV3TTItmbTJBg0ySk7/M4 ggMQ== X-Received: by 10.52.98.5 with SMTP id ee5mr25368978vdb.102.1360768247564; Wed, 13 Feb 2013 07:10:47 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.221.4.5 with SMTP id oa5csp200061vcb; Wed, 13 Feb 2013 07:10:46 -0800 (PST) X-Received: by 10.204.150.141 with SMTP id y13mr6609959bkv.50.1360768246342; Wed, 13 Feb 2013 07:10:46 -0800 (PST) Received: from mombin.canonical.com (mombin.canonical.com. [91.189.95.16]) by mx.google.com with ESMTP id 3si34231774bka.171.2013.02.13.07.10.45; Wed, 13 Feb 2013 07:10:46 -0800 (PST) Received-SPF: neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) client-ip=91.189.95.16; Authentication-Results: mx.google.com; spf=neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) smtp.mail=linaro-mm-sig-bounces@lists.linaro.org Received: from localhost ([127.0.0.1] helo=mombin.canonical.com) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U5dyr-0007N3-2x; Wed, 13 Feb 2013 15:10:41 +0000 Received: from mga09.intel.com ([134.134.136.24]) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U5dyp-0007My-QY for linaro-mm-sig@lists.linaro.org; Wed, 13 Feb 2013 15:10:39 +0000 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 13 Feb 2013 07:09:18 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.84,657,1355126400"; d="scan'208";a="262128710" Received: from unknown (HELO localhost) ([10.252.120.81]) by orsmga001.jf.intel.com with ESMTP; 13 Feb 2013 07:10:34 -0800 From: Imre Deak To: linux-kernel@vger.kernel.org Date: Wed, 13 Feb 2013 17:10:23 +0200 Message-Id: <1360768224-18163-1-git-send-email-imre.deak@intel.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1360608604-3520-1-git-send-email-imre.deak@intel.com> References: <1360608604-3520-1-git-send-email-imre.deak@intel.com> Cc: Maxim Levitsky , linaro-mm-sig@lists.linaro.org, Tejun Heo , Andrew Morton Subject: [Linaro-mm-sig] [PATCH v3 1/2] lib/scatterlist: add simple page iterator X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Unified memory management interest group." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linaro-mm-sig-bounces@lists.linaro.org Errors-To: linaro-mm-sig-bounces@lists.linaro.org X-Gm-Message-State: ALoCoQmIAOx6/+SURqsv6cNagE4miKy4z41Oq+WPlLuxFD6iK0mxabkijAghUJyEU+5VzWE8HJ7+ Add an iterator to walk through a scatter list a page at a time starting at a specific page offset. As opposed to the mapping iterator this is meant to be small, performing well even in simple loops like collecting all pages on the scatterlist into an array or setting up an iommu table based on the pages' DMA address. v2: - sg_pgoffset pointed incorrectly at the next page not the current one. v3: - formatting fixes, documentation (Andrew) - uninline helper functions, as they are too big (Andrew) - support for terminating the iteration after a maximum number sglist->nents entries, needed by the next patch Signed-off-by: Imre Deak --- include/linux/scatterlist.h | 35 +++++++++++++++++++++++++++++++++++ lib/scatterlist.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 4bd6c06..788a853 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -231,6 +231,41 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, */ #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) +/* + * sg page iterator + * + * Iterates over sg entries page-by-page. On each successful iteration, + * @piter->page points to the current page, @piter->sg to the sg holding this + * page and @piter->sg_pgoffset to the page's page offset within the sg. The + * iteration will stop either when a maximum number of sg entries was reached + * or a terminating sg (sg_last(sg) == true) was reached. + */ +struct sg_page_iter { + struct page *page; /* current page */ + struct scatterlist *sg; /* sg holding the page */ + unsigned int sg_pgoffset; /* page offset within the sg */ + + /* these are internal states, keep away */ + unsigned int __nents; /* remaining sg entries */ + int __pg_advance; /* nr pages to advance at the + * next step */ +}; + +bool __sg_page_iter_next(struct sg_page_iter *piter); +void __sg_page_iter_start(struct sg_page_iter *piter, + struct scatterlist *sglist, unsigned int nents, + unsigned long pgoffset); + +/** + * for_each_sg_page - iterate over the pages of the given sg list + * @sglist: sglist to iterate over + * @piter: page iterator to hold current page, sg, sg_pgoffset + * @nents: maximum number of sg entries to iterate over + * @pgoffset: starting page offset + */ +#define for_each_sg_page(sglist, piter, nents, pgoffset) \ + for (__sg_page_iter_start((piter), (sglist), (nents), (pgoffset)); \ + __sg_page_iter_next(piter);) /* * Mapping sg iterator diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 7874b01..a1d1564 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -394,6 +394,44 @@ int sg_alloc_table_from_pages(struct sg_table *sgt, } EXPORT_SYMBOL(sg_alloc_table_from_pages); +void __sg_page_iter_start(struct sg_page_iter *piter, + struct scatterlist *sglist, unsigned int nents, + unsigned long pgoffset) +{ + piter->__pg_advance = 0; + piter->__nents = nents; + + piter->page = NULL; + piter->sg = sglist; + piter->sg_pgoffset = pgoffset; +} +EXPORT_SYMBOL(__sg_page_iter_start); + +static int sg_page_count(struct scatterlist *sg) +{ + return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT; +} + +bool __sg_page_iter_next(struct sg_page_iter *piter) +{ + if (!piter->__nents || !piter->sg) + return false; + + piter->sg_pgoffset += piter->__pg_advance; + piter->__pg_advance = 1; + + while (piter->sg_pgoffset >= sg_page_count(piter->sg)) { + piter->sg_pgoffset -= sg_page_count(piter->sg); + piter->sg = sg_next(piter->sg); + if (!--piter->__nents || !piter->sg) + return false; + } + piter->page = nth_page(sg_page(piter->sg), piter->sg_pgoffset); + + return true; +} +EXPORT_SYMBOL(__sg_page_iter_next); + /** * sg_miter_start - start mapping iteration over a sg list * @miter: sg mapping iter to be started