Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp743800ybl; Wed, 4 Dec 2019 10:08:20 -0800 (PST) X-Google-Smtp-Source: APXvYqweCKtjnD/4b6li/8Lj//p/q4bQ8bDLhF0lZLF1Ig2qJ1v0oJxMIhbLeUNB5iOsxc4ZfmNJ X-Received: by 2002:a9d:6d06:: with SMTP id o6mr3548420otp.239.1575482900488; Wed, 04 Dec 2019 10:08:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1575482900; cv=none; d=google.com; s=arc-20160816; b=O/vCCYUpDtZehMu4ZUrPlzUQUGZJBSjHQlto5nd4aLbT7TZWDtWU4iBr1zTdzbjbei DnN9V5vu0TBH9zvX8m1GJlXIeVuigeztvbq7ZDLW2Yxk7mWMszANl4uzXW73DDjD5v7t P6v1IXZluTjtwrtAZ3JPF7FoOzXfZ1q8QLDRv9fLBOP5qEvWjEAVNmJKtHtmlpXkfOm0 NULYhyZwlVoMNNUWdq9+0L22vhGyZEd0+ckPlVPox9nMYeHybiT6oimV6b+G31l7hA18 OTr2cOGsGeGOv/3ZH4CeWT2CyfNAPUmxetF1BqqiwYIYdxpwCsRf64HbAJTJ2mD1foL9 /G0Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=0y9qM3zLUejeWzYc1RfTFoNEUbsSxDSrfzjpcsxNLww=; b=poIhyFGx3SImV824NfcYlzJ/9IVIVJgk6cF9IaQKBao9xzB0hJF9iQuZliL3/7oB2l C9VNM4lH3+HggEu3RoHkdTugy3ZGJj97qGe7H11PD++W3OOr7K+I2lnqHNkV30Ktq/7f CR++81CAzxOUQPTzn1l8CXrWfOCFU7HWd9XWKGaGvhsQvz4D5DiQeN0KH/EzwwL3TzyV nb2poLbNOAepNrBMKTMt4HBDzr/G1xNw66R64ZbigIHA4lMYyaiVTbrUQw6sdGmBT0kj 4qRraWacaCRP9e2MkcWXQBYclh0qU3FnaVTl5REtXWPJ7v+Ekidt9PmOpcumwaP0dA2C fDWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=XWXOZmdw; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w11si1478083oig.45.2019.12.04.10.08.07; Wed, 04 Dec 2019 10:08:20 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=XWXOZmdw; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730479AbfLDSGA (ORCPT + 99 others); Wed, 4 Dec 2019 13:06:00 -0500 Received: from mail.kernel.org ([198.145.29.99]:53206 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729308AbfLDSFy (ORCPT ); Wed, 4 Dec 2019 13:05:54 -0500 Received: from localhost (unknown [217.68.49.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C07162086D; Wed, 4 Dec 2019 18:05:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1575482753; bh=JB48OivgvDkEPWzY0v698UMzPguwajsoOOPQ3FdxZNA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XWXOZmdwobAEs0Bh3DfX/9Ojbw04zFvXjUIpqTiBrulIZS5+D5/1cpsgipf+6kwr/ xslHxZPQXRM4LGyDSZ5GlahT/J1P+2YCYTMokCb4p3YYNZp7M8fxVSLZh6otiTDOnR zq7SWGqy8Z93XguvX/AgHkQB8Vc4VCMzv33AAmuA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alexey Skidanov , Andrew Morton , Logan Gunthorpe , Daniel Mentz , Mathieu Desnoyers , Laura Abbott , Linus Torvalds , Sasha Levin Subject: [PATCH 4.14 121/209] lib/genalloc.c: fix allocation of aligned buffer from non-aligned chunk Date: Wed, 4 Dec 2019 18:55:33 +0100 Message-Id: <20191204175331.411882763@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191204175321.609072813@linuxfoundation.org> References: <20191204175321.609072813@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexey Skidanov [ Upstream commit 52fbf1134d479234d7e64ba9dcbaea23405f229e ] gen_pool_alloc_algo() uses different allocation functions implementing different allocation algorithms. With gen_pool_first_fit_align() allocation function, the returned address should be aligned on the requested boundary. If chunk start address isn't aligned on the requested boundary, the returned address isn't aligned too. The only way to get properly aligned address is to initialize the pool with chunks aligned on the requested boundary. If want to have an ability to allocate buffers aligned on different boundaries (for example, 4K, 1MB, ...), the chunk start address should be aligned on the max possible alignment. This happens because gen_pool_first_fit_align() looks for properly aligned memory block without taking into account the chunk start address alignment. To fix this, we provide chunk start address to gen_pool_first_fit_align() and change its implementation such that it starts looking for properly aligned block with appropriate offset (exactly as is done in CMA). Link: https://lkml.kernel.org/lkml/a170cf65-6884-3592-1de9-4c235888cc8a@intel.com Link: http://lkml.kernel.org/r/1541690953-4623-1-git-send-email-alexey.skidanov@intel.com Signed-off-by: Alexey Skidanov Reviewed-by: Andrew Morton Cc: Logan Gunthorpe Cc: Daniel Mentz Cc: Mathieu Desnoyers Cc: Laura Abbott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- include/linux/genalloc.h | 13 +++++++------ lib/genalloc.c | 20 ++++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 872f930f1b06d..dd0a452373e71 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -51,7 +51,8 @@ typedef unsigned long (*genpool_algo_t)(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, - void *data, struct gen_pool *pool); + void *data, struct gen_pool *pool, + unsigned long start_addr); /* * General purpose special memory pool descriptor. @@ -131,24 +132,24 @@ extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data, - struct gen_pool *pool); + struct gen_pool *pool, unsigned long start_addr); extern unsigned long gen_pool_fixed_alloc(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, - void *data, struct gen_pool *pool); + void *data, struct gen_pool *pool, unsigned long start_addr); extern unsigned long gen_pool_first_fit_align(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, - void *data, struct gen_pool *pool); + void *data, struct gen_pool *pool, unsigned long start_addr); extern unsigned long gen_pool_first_fit_order_align(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, - void *data, struct gen_pool *pool); + void *data, struct gen_pool *pool, unsigned long start_addr); extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data, - struct gen_pool *pool); + struct gen_pool *pool, unsigned long start_addr); extern struct gen_pool *devm_gen_pool_create(struct device *dev, diff --git a/lib/genalloc.c b/lib/genalloc.c index ca06adc4f4451..5deb25c40a5a1 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -311,7 +311,7 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, end_bit = chunk_size(chunk) >> order; retry: start_bit = algo(chunk->bits, end_bit, start_bit, - nbits, data, pool); + nbits, data, pool, chunk->start_addr); if (start_bit >= end_bit) continue; remain = bitmap_set_ll(chunk->bits, start_bit, nbits); @@ -525,7 +525,7 @@ EXPORT_SYMBOL(gen_pool_set_algo); */ unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data, - struct gen_pool *pool) + struct gen_pool *pool, unsigned long start_addr) { return bitmap_find_next_zero_area(map, size, start, nr, 0); } @@ -543,16 +543,19 @@ EXPORT_SYMBOL(gen_pool_first_fit); */ unsigned long gen_pool_first_fit_align(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data, - struct gen_pool *pool) + struct gen_pool *pool, unsigned long start_addr) { struct genpool_data_align *alignment; - unsigned long align_mask; + unsigned long align_mask, align_off; int order; alignment = data; order = pool->min_alloc_order; align_mask = ((alignment->align + (1UL << order) - 1) >> order) - 1; - return bitmap_find_next_zero_area(map, size, start, nr, align_mask); + align_off = (start_addr & (alignment->align - 1)) >> order; + + return bitmap_find_next_zero_area_off(map, size, start, nr, + align_mask, align_off); } EXPORT_SYMBOL(gen_pool_first_fit_align); @@ -567,7 +570,7 @@ EXPORT_SYMBOL(gen_pool_first_fit_align); */ unsigned long gen_pool_fixed_alloc(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data, - struct gen_pool *pool) + struct gen_pool *pool, unsigned long start_addr) { struct genpool_data_fixed *fixed_data; int order; @@ -601,7 +604,8 @@ EXPORT_SYMBOL(gen_pool_fixed_alloc); */ unsigned long gen_pool_first_fit_order_align(unsigned long *map, unsigned long size, unsigned long start, - unsigned int nr, void *data, struct gen_pool *pool) + unsigned int nr, void *data, struct gen_pool *pool, + unsigned long start_addr) { unsigned long align_mask = roundup_pow_of_two(nr) - 1; @@ -624,7 +628,7 @@ EXPORT_SYMBOL(gen_pool_first_fit_order_align); */ unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, void *data, - struct gen_pool *pool) + struct gen_pool *pool, unsigned long start_addr) { unsigned long start_bit = size; unsigned long len = size + 1; -- 2.20.1