Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp228077imu; Thu, 8 Nov 2018 07:30:31 -0800 (PST) X-Google-Smtp-Source: AJdET5eY0R1sF0O6Laz0y8Ge23DRkvjP8R9nr/0VwsMtdv5ANeEPhmPkIfQ6W1ihDciqsFrRMT5S X-Received: by 2002:a17:902:59d6:: with SMTP id d22-v6mr4962759plj.116.1541691031300; Thu, 08 Nov 2018 07:30:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541691031; cv=none; d=google.com; s=arc-20160816; b=ySVVFB/r4xY09RpkTYHZrM6Mt7yEHrL8cROtMBEcpBNsjiiP0yw93sNbgelQRQyQHK hSyCLBwVbbwaX2ssi0c+Xyilk0sQ2HI31HTpz2qnpGbPB1vjfisMY6epPjli30Y2bWdP DrNW/drCWQKu0nokoWtpLNYum1qvMeA9BztdFtZ+8wvxogTgyMFVcH7P9z8XsQy5w2UN 7VksX1SeKjnvaeuyKRglJuHxGLZimtB8cQ8OqNcjFMpcIal85OpZJimneQUA+Axebeju a2AZCejNdcLvJSXgFmuJpwH/BZ0NYZWcilji1tCEWpxts6aQUB81BoP5+64JsGjxAVrN o7Jw== 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=T7rWNChgq+n0iS6XFr8UEv2Gecobq1y3TyJg+DCxgoA=; b=gxo7rDgLOngnc1OmEZlIGZbuOV5e4RnmCU37df3a+mx09+40yEAsLPcHONbxGxc4zp UXrXnu1N4o3u4NxLW/KBggWtCASNynqcIw3zdywNGNSWUX7pLb/pmxGhYormrCSfNqMv Tr1uPjzFCZiDNTuuvQaao0D50vYs57Wx9thPjrriDRwU/LQ/5UvIozjgfFXa5iAiGbd4 W46ju51ZTduxU7lBDP4f9Xn+XSVh5f1JOKhBwYLi6oflvyH6R16y7u4pAulpBwZcDY2c HD8m9FdNjA0nymzJ+IXitTLSUB+VN4Xn3jzrh9cHdg+eQY9gjbG4lj+O860eXsF+K9Os XWjA== 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 f10si3939125pgl.528.2018.11.08.07.30.14; Thu, 08 Nov 2018 07:30:31 -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 S1726975AbeKIBEO (ORCPT + 99 others); Thu, 8 Nov 2018 20:04:14 -0500 Received: from mga11.intel.com ([192.55.52.93]:53048 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726469AbeKIBEO (ORCPT ); Thu, 8 Nov 2018 20:04:14 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 Nov 2018 07:28:13 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,480,1534834800"; d="scan'208";a="106409715" Received: from kohsamui.iil.intel.com ([10.236.193.12]) by fmsmga001.fm.intel.com with ESMTP; 08 Nov 2018 07:28:11 -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 v2] lib/genaloc: Fix allocation of aligned buffer from non-aligned chunk Date: Thu, 8 Nov 2018 17:29:13 +0200 Message-Id: <1541690953-4623-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 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 it done in CMA). Link: https://lkml.kernel.org/lkml/a170cf65-6884-3592-1de9-4c235888cc8a@intel.com Signed-off-by: Alexey Skidanov --- Changes: v2: Correct typos Add more details to changelog 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..5deb25c 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.7.4