linux_dsm_epyc7002/drivers/base/regmap
Lars-Peter Clausen 1bc8da4e14 regmap: rbtree: Avoid overlapping nodes
When searching for a suitable node that should be used for inserting a new
register, which does not fall within the range of any existing node, we not
only looks for nodes which are directly adjacent to the new register, but
for nodes within a certain proximity. This is done to avoid creating lots
of small nodes with just a few registers spacing in between, which would
increase memory usage as well as tree traversal time.

This means there might be multiple node candidates which fall within the
proximity range of the new register. If we choose the first node we
encounter, under certain register insertion patterns it is possible to end
up with overlapping ranges. This will break order in the rbtree and can
cause the cached register value to become corrupted.

E.g. take the simplified example where the proximity range is 2 and the
register insertion sequence is 1, 4, 2, 3, 5.
 * Insert of register 1 creates a new node, this is the root of the rbtree
 * Insert of register 4 creates a new node, which is inserted to the right
   of the root.
 * Insert of register 2 gets inserted to the first node
 * Insert of register 3 gets inserted to the first node
 * Insert of register 5 also gets inserted into the first node since
   this is the first node encountered and it is within the proximity range.
   Now there are two overlapping nodes.

To avoid this always choose the node that is closest to the new register.
This will ensure that nodes will not overlap. The tree traversal is still
done as a binary search, we just don't stop at the first node found. So the
complexity of the algorithm stays within the same order.

Ideally if a new register is in the range of two adjacent blocks those
blocks should be merged, but that is a much more invasive change and left
for later.

The issue was initially introduced in commit 472fdec738 ("regmap: rbtree:
Reduce number of nodes, take 2"), but became much more exposed by commit
6399aea629 ("regmap: rbtree: When adding a reg do a bsearch for target
node") which changed the order in which nodes are looked-up.

Fixes: 6399aea629 ("regmap: rbtree: When adding a reg do a bsearch for target node")
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
2016-08-04 16:55:26 +01:00
..
internal.h regmap: Fix implicit inclusion of device.h 2016-03-30 08:46:11 -07:00
Kconfig regmap: ac97: Add generic AC'97 callbacks 2014-11-19 10:28:14 +00:00
Makefile regmap: Move tracing header into drivers/base/regmap 2015-03-19 22:22:45 +00:00
regcache-flat.c regcache: flat: Require max_registers to be set 2016-03-29 09:51:04 -07:00
regcache-lzo.c regmap: replace kmalloc with kmalloc_array 2015-11-20 12:27:59 +00:00
regcache-rbtree.c regmap: rbtree: Avoid overlapping nodes 2016-08-04 16:55:26 +01:00
regcache.c regmap: cache: Fix typo in cache_bypass parameter description 2016-03-23 18:12:39 +00:00
regmap-ac97.c regmap: Move documentation to regmap.h 2015-08-11 17:21:44 +01:00
regmap-debugfs.c regmap: debugfs: Use seq_file for the access map 2016-01-05 18:32:22 +00:00
regmap-i2c.c regmap-i2c: Use i2c block command only if register value width is 8 bit 2016-06-22 13:50:51 +01:00
regmap-irq.c regmap: irq: Add support to call client specific pre/post interrupt service 2016-06-03 00:41:15 +01:00
regmap-mmio.c Merge remote-tracking branches 'regmap/fix/be', 'regmap/fix/doc' and 'regmap/fix/spmi' into regmap-linus 2016-05-13 10:36:10 +01:00
regmap-spi.c regmap: Move documentation to regmap.h 2015-08-11 17:21:44 +01:00
regmap-spmi.c regmap: spmi: Fix regmap_spmi_ext_read in multi-byte case 2016-04-15 10:11:45 +01:00
regmap.c regmap: Support bulk writes for devices without raw formatting 2016-06-29 19:48:00 +01:00
trace.h regmap: Move tracing header into drivers/base/regmap 2015-03-19 22:22:45 +00:00