From nobody Sun May 10 06:03:31 2026 Received: from polaris.svanheule.net (polaris.svanheule.net [84.16.241.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E105E18A6AD for ; Tue, 31 Dec 2024 10:08:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=84.16.241.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735639723; cv=none; b=lkhabMS781UFe/CErjVfpiYYxxWea+82cFiBEODh5esPsbWEcxKvdKYDTtAgj6EiqhczLkeDvyu8rY05u/GPFtiwOJ2LHYXVo3dCFR493BvuSTxDQLU2d9hrY2yTqEbgNnxDplav96az8295RHjgHJNp+l9BCNCL/q3wsm+uwns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735639723; c=relaxed/simple; bh=OWJpz7Jec9mHCnxcGVQuh/jRZ8rG4NCIuE40KV5+AIQ=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=sAhwALElGuyEgiXjdlaMxH5B2EMnUsh1nVks9FI3jaWcn/8lwQ6vSbDjprMhvjyt5p56GzUApLD/iSzRib36SMJmTUnZimFORL2dPofeesTARqVbhl85Azo2x6RmmzwjiF61XaxeCVJ4JVFKRkycJgLtGjHAsLQlw7x9uvam8QA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=svanheule.net; spf=pass smtp.mailfrom=svanheule.net; dkim=pass (2048-bit key) header.d=svanheule.net header.i=@svanheule.net header.b=nZlaHenx; arc=none smtp.client-ip=84.16.241.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=svanheule.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=svanheule.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=svanheule.net header.i=@svanheule.net header.b="nZlaHenx" Received: from terra.vega.svanheule.net (unknown [94.110.49.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 9E8145957CF; Tue, 31 Dec 2024 11:03:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1735639400; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=MdOJWjsSlqVf7JBpeKMxSXWxmFSn0j1Q5thD21iVCEk=; b=nZlaHenxXemj3LDSszr/ZcJRjnpWh8e9Mw5JKo/MtgXrZ2jP/7m9FLC1pdQt0QnhRuZJfg wuxBKvMz+QYsS+4uG7sBIdW60gc/FEZMguP/Kb2TLkrXTriqxcp3U0Dy+RgG4vdAnZdpIZ K4iw03UjBZq8kBYezjKXwLzIY8VljPqq7lj4onvSutaytK+U9xV/yvRHeotKcKyAJTkM4m itu2zNj3MwYp5s7hOxSQp1ishWJSFS+rgZWdluvCyFcRSJ5III6oDtEe3uPQJE7UuBj/Jd d03A5H6SG13Y6K5KST/vzqwb3agxrrUGnLm477lqrpPEPA7rUMZUlaib310BAQ== From: Sander Vanheule To: Mark Brown , Greg Kroah-Hartman , "Rafael J. Wysocki" , linux-kernel@vger.kernel.org Cc: Sander Vanheule Subject: [PATCH] regmap: add cache validity to REGCACHE_FLAT Date: Tue, 31 Dec 2024 11:02:56 +0100 Message-ID: <20241231100256.194753-1-sander@svanheule.net> X-Mailer: git-send-email 2.47.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The flat regcache will always assume the data in the cache is valid. Since the cache takes priority over hardware values, this may shadow the actual state of the device. This is not the case with REGCACHE_RBTREE for example, which makes these implementation behave differently. Add a new containing cache structure with the flat data table and a bitmap indicating cache validity. Use this to provide an implementation for regcache_ops.drop. Since this makes the flat cache behave more like other caches, a special case in the read_writeonly unit test can also be dropped. This reverts commit d0c99ffe2126 ("regmap: Allow reads from write only registers with the flat cache"). Signed-off-by: Sander Vanheule --- drivers/base/regmap/regcache-flat.c | 70 ++++++++++++++++++++++++----- drivers/base/regmap/regmap-kunit.c | 15 ++----- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regc= ache-flat.c index f36d3618b67c..4bdf2e58ade1 100644 --- a/drivers/base/regmap/regcache-flat.c +++ b/drivers/base/regmap/regcache-flat.c @@ -6,6 +6,8 @@ // // Author: Mark Brown =20 +#include +#include #include #include #include @@ -18,34 +20,65 @@ static inline unsigned int regcache_flat_get_index(cons= t struct regmap *map, return regcache_get_index_by_order(map, reg); } =20 +struct regcache_flat_data { + unsigned int *data; + unsigned long *valid; +}; + static int regcache_flat_init(struct regmap *map) { int i; - unsigned int *cache; + unsigned int cache_size; + struct regcache_flat_data *cache =3D NULL; + unsigned long *cache_valid =3D NULL; + unsigned int *cache_data =3D NULL; =20 if (!map || map->reg_stride_order < 0 || !map->max_register_is_set) return -EINVAL; =20 - map->cache =3D kcalloc(regcache_flat_get_index(map, map->max_register) - + 1, sizeof(unsigned int), map->alloc_flags); - if (!map->cache) + cache_size =3D regcache_flat_get_index(map, map->max_register) + 1; + cache_data =3D kcalloc(cache_size, sizeof(unsigned int), map->alloc_flags= ); + if (!cache_data) return -ENOMEM; =20 + cache_valid =3D bitmap_zalloc(cache_size, map->alloc_flags); + if (!cache_valid) + goto err_free_valid; + + map->cache =3D kmalloc(sizeof(*cache), map->alloc_flags); + if (!map->cache) + goto err_free; + cache =3D map->cache; + cache->valid =3D cache_valid; + cache->data =3D cache_data; =20 for (i =3D 0; i < map->num_reg_defaults; i++) { unsigned int reg =3D map->reg_defaults[i].reg; unsigned int index =3D regcache_flat_get_index(map, reg); =20 - cache[index] =3D map->reg_defaults[i].def; + cache->data[index] =3D map->reg_defaults[i].def; + __set_bit(index, cache->valid); } =20 return 0; + +err_free: + kfree(cache_data); +err_free_valid: + bitmap_free(cache_valid); + return -ENOMEM; } =20 static int regcache_flat_exit(struct regmap *map) { - kfree(map->cache); + struct regcache_flat_data *cache =3D map->cache; + + if (cache) { + bitmap_free(cache->valid); + kfree(cache->data); + } + kfree(cache); map->cache =3D NULL; =20 return 0; @@ -54,10 +87,13 @@ static int regcache_flat_exit(struct regmap *map) static int regcache_flat_read(struct regmap *map, unsigned int reg, unsigned int *value) { - unsigned int *cache =3D map->cache; + struct regcache_flat_data *cache =3D map->cache; unsigned int index =3D regcache_flat_get_index(map, reg); =20 - *value =3D cache[index]; + if (!test_bit(index, cache->valid)) + return -ENOENT; + + *value =3D cache->data[index]; =20 return 0; } @@ -65,10 +101,23 @@ static int regcache_flat_read(struct regmap *map, static int regcache_flat_write(struct regmap *map, unsigned int reg, unsigned int value) { - unsigned int *cache =3D map->cache; + struct regcache_flat_data *cache =3D map->cache; unsigned int index =3D regcache_flat_get_index(map, reg); =20 - cache[index] =3D value; + cache->data[index] =3D value; + __set_bit(index, cache->valid); + + return 0; +} + +static int regcache_flat_drop(struct regmap *map, unsigned int min, + unsigned int max) +{ + struct regcache_flat_data *cache =3D map->cache; + unsigned int index_min =3D regcache_flat_get_index(map, min); + unsigned int index_max =3D regcache_flat_get_index(map, max); + + bitmap_clear(cache->valid, index_min, index_max - index_min); =20 return 0; } @@ -80,4 +129,5 @@ struct regcache_ops regcache_flat_ops =3D { .exit =3D regcache_flat_exit, .read =3D regcache_flat_read, .write =3D regcache_flat_write, + .drop =3D regcache_flat_drop, }; diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regma= p-kunit.c index 64ea340950b6..676f1a91c352 100644 --- a/drivers/base/regmap/regmap-kunit.c +++ b/drivers/base/regmap/regmap-kunit.c @@ -567,18 +567,9 @@ static void read_writeonly(struct kunit *test) for (i =3D 0; i < BLOCK_TEST_SIZE; i++) data->read[i] =3D false; =20 - /* - * Try to read all the registers, the writeonly one should - * fail if we aren't using the flat cache. - */ - for (i =3D 0; i < BLOCK_TEST_SIZE; i++) { - if (config.cache_type !=3D REGCACHE_FLAT) { - KUNIT_EXPECT_EQ(test, i !=3D 5, - regmap_read(map, i, &val) =3D=3D 0); - } else { - KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val)); - } - } + /* Try to read all the registers, the writeonly one should fail */ + for (i =3D 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, i !=3D 5, regmap_read(map, i, &val) =3D=3D 0); =20 /* Did we trigger a hardware access? */ KUNIT_EXPECT_FALSE(test, data->read[5]); --=20 2.47.1