Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp821065ybl; Wed, 4 Dec 2019 11:25:38 -0800 (PST) X-Google-Smtp-Source: APXvYqwdJprf2EL6bURwXAYlgbRzcJUHJbwGdPNbKTpW2KxSR5fGw6Xj3Yx8ja9ECzaf8lkpdXFy X-Received: by 2002:a9d:4e97:: with SMTP id v23mr3619163otk.201.1575487538249; Wed, 04 Dec 2019 11:25:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1575487538; cv=none; d=google.com; s=arc-20160816; b=h329ZmrKgKhPhKNSovlomxWhDr+che5ibeyMzFd88lH83AHGygAaQH4to9pDOof4yr cb6+HTs73aTy4Z3m4yLV6b4AuZY7mhEqbLpDPoN7QOErvYpXUlioA7YFBGuYP75lsil5 GtEYZrMGF7BZ+BLLen4qfEo2kQrXXnzKOYrjk4yodAfwBetgZeeWxf76KWpW3WOFWt18 DnZLQs3y98uH/GIaLtpyaQdMQOT30QaU0twJlU8/tUghN4TPNA9bV+HIvBrbmjM/ZKTM i8lubsc/8zylXHpCGRi2zeV4z61tNkoZ7kxuzXdNesbzfS8128E//qQGzfP7J4dimR0N wusQ== 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=sJEIhGVhB/iOkfRHnnFzab9MMMyBYFmwpWNfI7oc5q0=; b=UBQxK5sT2UZvGWbU20O0hA/c95M5683AAhrOxba55f/0sBH2RseuD9i694n6SC8jbz R5bnwmXQp5gxfKm6xo9Y9W7BCI5lix6UmRpXNoyXwPR4X9vYxiO0WE76wYgsmTtYct4g DR/8pHSM0ZDEJDb2cZaKwi1c+zvXcO6g1tsBor1Vy3sPe1SiBJ5HtUoEtKr14RAfiED8 ZAeuqSZm9ga4fdDffPZz/cHYuIyXtx6LNACVfLgvbfnJ4Mi066Sf6d+PZ0zGc4GzOYAg ZU+73HQVnrhBGvkbPBo6TWjzZvKzq+1JJ0jZu1AkIhxv8bFNk1OrE4KolprhqANpshbX gTZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=qtAZe80F; 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 73si3558421otj.82.2019.12.04.11.25.24; Wed, 04 Dec 2019 11:25:38 -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=qtAZe80F; 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 S1731732AbfLDSNQ (ORCPT + 99 others); Wed, 4 Dec 2019 13:13:16 -0500 Received: from mail.kernel.org ([198.145.29.99]:42214 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731721AbfLDSNO (ORCPT ); Wed, 4 Dec 2019 13:13:14 -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 80BCC20674; Wed, 4 Dec 2019 18:13:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1575483193; bh=rkaZ7GFBTezRs+c1psX1fLT4Sv2NwyXuvcK7sz8Rltk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qtAZe80FOGRJCMxvrbnx6FvN7Vng0HcBiYae+ITk01PhO2+BELQeL/jW6m/69L9qd aOTS83v57BniLwtt2r1X8yLv3Z1HHJBUiDWYK9CMslWsezBC8NNp4z4ECXyC7F0vmg qf1qpegPbC7MckHvNbJa3hERdnTCYetd9QQ1XDmA= 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.9 083/125] lib/genalloc.c: fix allocation of aligned buffer from non-aligned chunk Date: Wed, 4 Dec 2019 18:56:28 +0100 Message-Id: <20191204175324.082049865@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191204175308.377746305@linuxfoundation.org> References: <20191204175308.377746305@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 206fe3bcccccd..575f2dee8cf71 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -50,7 +50,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. @@ -130,24 +131,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