Patch "regmap: Ensure range selector registers are updated after cache sync" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    regmap: Ensure range selector registers are updated after cache sync

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     regmap-ensure-range-selector-registers-are-updated-a.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 7fd9b1e6246b0853d02e64b75cde5631d134a5cc
Author: Mark Brown <broonie@xxxxxxxxxx>
Date:   Thu Oct 26 16:49:19 2023 +0100

    regmap: Ensure range selector registers are updated after cache sync
    
    [ Upstream commit 0ec7731655de196bc1e4af99e495b38778109d22 ]
    
    When we sync the register cache we do so with the cache bypassed in order
    to avoid overhead from writing the synced values back into the cache. If
    the regmap has ranges and the selector register for those ranges is in a
    register which is cached this has the unfortunate side effect of meaning
    that the physical and cached copies of the selector register can be out of
    sync after a cache sync. The cache will have whatever the selector was when
    the sync started and the hardware will have the selector for the register
    that was synced last.
    
    Fix this by rewriting all cached selector registers after every sync,
    ensuring that the hardware and cache have the same content. This will
    result in extra writes that wouldn't otherwise be needed but is simple
    so hopefully robust. We don't read from the hardware since not all
    devices have physical read support.
    
    Given that nobody noticed this until now it is likely that we are rarely if
    ever hitting this case.
    
    Reported-by: Hector Martin <marcan@xxxxxxxxx>
    Cc: stable@xxxxxxxxxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20231026-regmap-fix-selector-sync-v1-1-633ded82770d@xxxxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 0b517a83c4493..b04e8c90aca20 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -325,6 +325,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
 	return 0;
 }
 
+static int rbtree_all(const void *key, const struct rb_node *node)
+{
+	return 0;
+}
+
 /**
  * regcache_sync - Sync the register cache with the hardware.
  *
@@ -342,6 +347,7 @@ int regcache_sync(struct regmap *map)
 	unsigned int i;
 	const char *name;
 	bool bypass;
+	struct rb_node *node;
 
 	if (WARN_ON(map->cache_type == REGCACHE_NONE))
 		return -EINVAL;
@@ -386,6 +392,30 @@ int regcache_sync(struct regmap *map)
 	map->async = false;
 	map->cache_bypass = bypass;
 	map->no_sync_defaults = false;
+
+	/*
+	 * If we did any paging with cache bypassed and a cached
+	 * paging register then the register and cache state might
+	 * have gone out of sync, force writes of all the paging
+	 * registers.
+	 */
+	rb_for_each(node, 0, &map->range_tree, rbtree_all) {
+		struct regmap_range_node *this =
+			rb_entry(node, struct regmap_range_node, node);
+
+		/* If there's nothing in the cache there's nothing to sync */
+		ret = regcache_read(map, this->selector_reg, &i);
+		if (ret != 0)
+			continue;
+
+		ret = _regmap_write(map, this->selector_reg, i);
+		if (ret != 0) {
+			dev_err(map->dev, "Failed to write %x = %x: %d\n",
+				this->selector_reg, i, ret);
+			break;
+		}
+	}
+
 	map->unlock(map->lock_arg);
 
 	regmap_async_complete(map);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux