summaryrefslogtreecommitdiff
path: root/drivers/cxl
diff options
context:
space:
mode:
authorQuanquan Cao <caoqq@fujitsu.com>2024-01-24 12:15:26 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-02-01 03:17:12 +0300
commitec745eeff4d2824e983f6f00bbff2a8a8003972b (patch)
treeed81d8b7b130cb6dd6b176f7a31a5090a8fe13cc /drivers/cxl
parent1111abee590ddc3f86e5fb119a9def756c217bb1 (diff)
downloadlinux-ec745eeff4d2824e983f6f00bbff2a8a8003972b.tar.xz
cxl/region:Fix overflow issue in alloc_hpa()
commit d76779dd3681c01a4c6c3cae4d0627c9083e0ee6 upstream. Creating a region with 16 memory devices caused a problem. The div_u64_rem function, used for dividing an unsigned 64-bit number by a 32-bit one, faced an issue when SZ_256M * p->interleave_ways. The result surpassed the maximum limit of the 32-bit divisor (4G), leading to an overflow and a remainder of 0. note: At this point, p->interleave_ways is 16, meaning 16 * 256M = 4G To fix this issue, I replaced the div_u64_rem function with div64_u64_rem and adjusted the type of the remainder. Signed-off-by: Quanquan Cao <caoqq@fujitsu.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Fixes: 23a22cd1c98b ("cxl/region: Allocate HPA capacity to regions") Cc: <stable@vger.kernel.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/cxl')
-rw-r--r--drivers/cxl/core/region.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 2f7187dbfa2d..5b7d848a6f01 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -450,7 +450,7 @@ static int alloc_hpa(struct cxl_region *cxlr, resource_size_t size)
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
struct cxl_region_params *p = &cxlr->params;
struct resource *res;
- u32 remainder = 0;
+ u64 remainder = 0;
lockdep_assert_held_write(&cxl_region_rwsem);
@@ -470,7 +470,7 @@ static int alloc_hpa(struct cxl_region *cxlr, resource_size_t size)
(cxlr->mode == CXL_DECODER_PMEM && uuid_is_null(&p->uuid)))
return -ENXIO;
- div_u64_rem(size, SZ_256M * p->interleave_ways, &remainder);
+ div64_u64_rem(size, (u64)SZ_256M * p->interleave_ways, &remainder);
if (remainder)
return -EINVAL;