From 3fe3a1bfef75efcdfbcca955fe1d47ec07215110 Mon Sep 17 00:00:00 2001
From: Marc Ferland <marc.ferland@sonatest.com>
Date: Mon, 18 Dec 2023 10:02:29 -0500
Subject: [PATCH] w1: ds2433: use the kernel bitmap implementation

The ds2433 driver uses the 'validcrc' variable to mark out which pages
have been successfully (crc is valid) retrieved from the eeprom and
placed in the internal 'memory' buffer (see CONFIG_W1_SLAVE_DS2433_CRC).

The current implementation assumes that the number of pages will never
go beyond 32 pages (bit field is a u32). This is fine for the ds2433
since it only has 16 pages.

On the ds28ec20 though, the number of pages increases to 80 which will
not fit on a single u32.

As a solution, I replaced the u32 variable with a standard bitmap and
set the number of bits to 32 which is the same size we had before.

Signed-off-by: Marc Ferland <marc.ferland@sonatest.com>
Link: https://lore.kernel.org/r/20231218150230.1992448-5-marc.ferland@sonatest.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 drivers/w1/slaves/w1_ds2433.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index 0c67082c8bb7..87df76094e03 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -28,6 +28,7 @@
 #define W1_PAGE_SIZE		32
 #define W1_PAGE_BITS		5
 #define W1_PAGE_MASK		0x1F
+#define W1_VALIDCRC_MAX		32
 
 #define W1_F23_READ_EEPROM	0xF0
 #define W1_F23_WRITE_SCRATCH	0x0F
@@ -48,8 +49,8 @@ static const struct ds2433_config config_f23 = {
 
 struct w1_f23_data {
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
-	u8	*memory;
-	u32	validcrc;
+	u8 *memory;
+	DECLARE_BITMAP(validcrc, W1_VALIDCRC_MAX);
 #endif
 	const struct ds2433_config *cfg;
 };
@@ -76,11 +77,11 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
 	u8	wrbuf[3];
 	int	off = block * W1_PAGE_SIZE;
 
-	if (data->validcrc & (1 << block))
+	if (test_bit(block, data->validcrc))
 		return 0;
 
 	if (w1_reset_select_slave(sl)) {
-		data->validcrc = 0;
+		bitmap_zero(data->validcrc, data->cfg->page_count);
 		return -EIO;
 	}
 
@@ -92,7 +93,7 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
 
 	/* cache the block if the CRC is valid */
 	if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
-		data->validcrc |= (1 << block);
+		set_bit(block, data->validcrc);
 
 	return 0;
 }
@@ -207,7 +208,7 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
 	/* Reset the bus to wake up the EEPROM (this may not be needed) */
 	w1_reset_bus(sl->master);
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
-	f23->validcrc &= ~(1 << (addr >> W1_PAGE_BITS));
+	clear_bit(addr >> W1_PAGE_BITS, f23->validcrc);
 #endif
 	return 0;
 }
@@ -290,11 +291,17 @@ static int w1_f23_add_slave(struct w1_slave *sl)
 	data->cfg = &config_f23;
 
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
+	if (data->cfg->page_count > W1_VALIDCRC_MAX) {
+		dev_err(&sl->dev, "page count too big for crc bitmap\n");
+		kfree(data);
+		return -EINVAL;
+	}
 	data->memory = kzalloc(data->cfg->eeprom_size, GFP_KERNEL);
 	if (!data->memory) {
 		kfree(data);
 		return -ENOMEM;
 	}
+	bitmap_zero(data->validcrc, data->cfg->page_count);
 #endif /* CONFIG_W1_SLAVE_DS2433_CRC */
 	sl->family_data = data;
 
-- 
2.30.9