From patchwork Wed Apr 10 03:08:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 2419081 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 871473FC71 for ; Wed, 10 Apr 2013 03:09:28 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UPlPL-0006QG-1N; Wed, 10 Apr 2013 03:09:11 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UPlPD-0002UH-5d; Wed, 10 Apr 2013 03:09:03 +0000 Received: from mail-qc0-x22d.google.com ([2607:f8b0:400d:c01::22d]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UPlOu-0002Sx-8s for linux-arm-kernel@lists.infradead.org; Wed, 10 Apr 2013 03:08:46 +0000 Received: by mail-qc0-f173.google.com with SMTP id b12so6324qca.18 for ; Tue, 09 Apr 2013 20:08:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=mp0UtuAVY0JbO8hLlH5RG8i3BR0SR38qVMNxDqz+yFE=; b=Tnpem6v3EoKkJlyn4QcdiGM0VxorluTS3rWFTdJY8voqwUj1bFshzPUo11Uag9pmM6 VMHGB2G6LlA2tgUq3Ex8+6dF++FPj9QtYnM3ohGns/OL28SxFvOHs57LJIGYGOvJ1PiN OE5oU1X92+h/OWHGpRUlL9orYHVIXNPN39ZpcSxFBXI4eGYhS63L6LNTygG431MAMqof dOtdHv/nURqSvXe8EkyhNpJmGF0R+gf8wrgnb5CrtRLA2wPBI2CKnG6FdUB++82z7g0x vW1Ev6dTJ36m5LuHCyT/Cm2CFtXOh9by4c3L9nbiivX1n9Lx+biwmZXlNdt4n/Itill4 +hrQ== X-Received: by 10.224.39.146 with SMTP id g18mr587886qae.31.1365563322921; Tue, 09 Apr 2013 20:08:42 -0700 (PDT) Received: from rob-laptop.grandenetworks.net (65-36-73-129.dyn.grandenetworks.net. [65.36.73.129]) by mx.google.com with ESMTPS id ed8sm20964127qeb.7.2013.04.09.20.08.41 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 09 Apr 2013 20:08:42 -0700 (PDT) From: Rob Herring To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 3/3] pstore/ram: avoid atomic accesses for ioremapped regions Date: Tue, 9 Apr 2013 22:08:17 -0500 Message-Id: <1365563297-12480-3-git-send-email-robherring2@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1365563297-12480-1-git-send-email-robherring2@gmail.com> References: <1365563297-12480-1-git-send-email-robherring2@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130409_230844_426455_1532BCE2 X-CRM114-Status: GOOD ( 12.85 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (robherring2[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (robherring2[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Tony Luck , Colin Cross , Kees Cook , Rob Herring , Anton Vorontsov X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Rob Herring For persistent RAM outside of main memory, the memory may have limitations on supported accesses. For internal RAM on highbank platform exclusive accesses are not supported and will hang the system. So atomic_cmpxchg cannot be used. This commit uses spinlock protection for buffer size and start updates on ioremapped regions instead. Signed-off-by: Rob Herring Cc: Anton Vorontsov Cc: Colin Cross Cc: Kees Cook Cc: Tony Luck Cc: linux-kernel@vger.kernel.org --- fs/pstore/ram_core.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index e126d9f..97e640b 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -46,7 +46,7 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz) } /* increase and wrap the start pointer, returning the old value */ -static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) +static size_t buffer_start_add_atomic(struct persistent_ram_zone *prz, size_t a) { int old; int new; @@ -62,7 +62,7 @@ static inline size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) } /* increase the size counter until it hits the max size */ -static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) +static void buffer_size_add_atomic(struct persistent_ram_zone *prz, size_t a) { size_t old; size_t new; @@ -78,6 +78,53 @@ static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); } +static DEFINE_RAW_SPINLOCK(buffer_lock); + +/* increase and wrap the start pointer, returning the old value */ +static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a) +{ + int old; + int new; + unsigned long flags; + + raw_spin_lock_irqsave(&buffer_lock, flags); + + old = atomic_read(&prz->buffer->start); + new = old + a; + while (unlikely(new > prz->buffer_size)) + new -= prz->buffer_size; + atomic_set(&prz->buffer->start, new); + + raw_spin_unlock_irqrestore(&buffer_lock, flags); + + return old; +} + +/* increase the size counter until it hits the max size */ +static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a) +{ + size_t old; + size_t new; + unsigned long flags; + + raw_spin_lock_irqsave(&buffer_lock, flags); + + old = atomic_read(&prz->buffer->size); + if (old == prz->buffer_size) + goto exit; + + new = old + a; + if (new > prz->buffer_size) + new = prz->buffer_size; + atomic_set(&prz->buffer->size, new); + +exit: + raw_spin_unlock_irqrestore(&buffer_lock, flags); +} + +static size_t (*buffer_start_add)(struct persistent_ram_zone *, size_t) = buffer_start_add_atomic; +static void (*buffer_size_add)(struct persistent_ram_zone *, size_t) = buffer_size_add_atomic; + static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, uint8_t *data, size_t len, uint8_t *ecc) { @@ -364,6 +411,9 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size) return NULL; } + buffer_start_add = buffer_start_add_locked; + buffer_size_add = buffer_size_add_locked; + return ioremap_wc(start, size); }