Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1781153imu; Tue, 6 Nov 2018 04:21:09 -0800 (PST) X-Google-Smtp-Source: AJdET5dXGQmCar2mRuqLkD6BxJAbOQKnXHLp9+NniuKUnu3rJORb7O6bRFOwsQswdhdNhyC0hJSM X-Received: by 2002:a65:41c2:: with SMTP id b2mr21532719pgq.67.1541506869789; Tue, 06 Nov 2018 04:21:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541506869; cv=none; d=google.com; s=arc-20160816; b=nWgDNqeJimxAYQc9K375H53A5EieysZ2rIbSjBXqfUVRe+o2vfDHyokjuq6Th6n20u xAi5OT0OAV75S/7p/mjK+ybQWkSRsNkBfVpu6I5xxU/MLlf4MAQpArEavPLseQ7Kl1ne +/Q/M0cGWiP6/Hly04WyC6sSQrqfGdXNo0j6JXBht+0FkeuGKwflvF4AYlWO8YrIpNHr wFh5Rcj7XKnziX/IprdQwTufTMlBi7G2FJBBd5DVhlV6xa+gw7+MtfNHS7mHQpfqKY59 r6gNT/k74CFak4T19IGT4r1WYNemcWc7pac3j1YAlIalJe8JnWHMt9RKXplRCYmCYJSi o0Pg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from; bh=9cCnKf9WlE4Aonr5QGNn//o9zS5NU46hWPQrskg9oBk=; b=EfYCLlol7oK6ODWzlTrjW7cHwtcncV24WdmnE4FDXLcAzwLjKh06Q7UcGEGx9o035I +ddFqN8iXKPw8kbUOV0vTFD9foDVsqoRFVD0daBK91aRO7oKBgpcmbvdOmoNEkw11Quk 6zIfWWCIc5Kt6eTHel012p50hLbp9VXz9gwMMs1cfaaRYJPV9B0TOBZXsPjsirz6npW1 KfjhYfGhkQyjm8Z7GWS89XicEzqaPJYZXuSSvmBIoj7vnn0LnTdNmHgeqQGuUfxTXgiy GTf0xG/eb2YpbNhu80IK/U0m3MXSK6A2LGMdpsT1Xw6/SdPdbPyTvGOuDAme1NS4PHM/ TXSA== ARC-Authentication-Results: i=1; mx.google.com; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 31-v6si19358570plk.397.2018.11.06.04.20.54; Tue, 06 Nov 2018 04:21:09 -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; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730423AbeKFVo4 (ORCPT + 99 others); Tue, 6 Nov 2018 16:44:56 -0500 Received: from mga17.intel.com ([192.55.52.151]:10458 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726976AbeKFVo4 (ORCPT ); Tue, 6 Nov 2018 16:44:56 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Nov 2018 04:19:58 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,471,1534834800"; d="scan'208";a="105824636" Received: from kohsamui.iil.intel.com ([10.236.193.12]) by orsmga001.jf.intel.com with ESMTP; 06 Nov 2018 04:19:56 -0800 From: Alexey Skidanov To: sbates@raithlin.com, logang@deltatee.com, danielmentz@google.com, akpm@linux-foundation.org, mathieu.desnoyers@efficios.com Cc: linux-kernel@vger.kernel.org, labbott@redhat.com, Alexey Skidanov Subject: [PATCH] lib/genaloc: Fix allocation of aligned buffer from non-aligned chunk Date: Tue, 6 Nov 2018 14:20:53 +0200 Message-Id: <1541506853-10685-1-git-send-email-alexey.skidanov@intel.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On success, gen_pool_first_fit_align() returns the bit number such that chunk_start_addr + (bit << order) is properly aligned. On failure, the bitmap size parameter is returned. When the chunk_start_addr isn't aligned properly, the chunk_start_addr + (bit << order) isn't aligned too. To fix this, gen_pool_first_fit_align() takes into account the chunk_start_addr alignment and returns the bit value such that chunk_start_addr + (bit << order) is properly aligned (exactly as it done in CMA). Link: https://lkml.kernel.org/lkml/a170cf65-6884-3592-1de9-4c235888cc8a@intel.com Signed-off-by: Alexey Skidanov --- 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 872f930..dd0a452 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 ca06adc..033817a 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_add) { 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_add) { 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_add) { unsigned long start_bit = size; unsigned long len = size + 1; -- 2.7.4