mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
Merge tag 'regmap-fix-v7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap fixes from Mark Brown: "These fix some issues which were noticed in some drivers where caches were not fully resynced after suspend. Drivers are supposed to be sorting the table of register defaults they provide to the core and the core was relying on that but it turns out there are many cases where this does not happen, it's easy to get wrong when using named defines for registers rather than numbers. It is more robust to remove the requirement for sorting and instead have the core ensure everything it needs sorting is sorted so do that. There will be patches during the merge window sorting the tables in drivers since it is more efficient to do that but this will just be a minor performance win rather than a correctness fix" * tag 'regmap-fix-v7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regcache: Sort the local copy of an unsorted reg_defaults array regcache: Use a consistent sort for defaults table
This commit is contained in:
@@ -123,6 +123,8 @@ static void regcache_hw_exit(struct regmap *map)
|
||||
|
||||
int regcache_init(struct regmap *map, const struct regmap_config *config)
|
||||
{
|
||||
bool sort_defaults = false;
|
||||
unsigned int reg_prev = 0;
|
||||
int count = 0;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -149,10 +151,16 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->num_reg_defaults; i++)
|
||||
for (i = 0; i < config->num_reg_defaults; i++) {
|
||||
if (config->reg_defaults[i].reg % map->reg_stride)
|
||||
return -EINVAL;
|
||||
|
||||
if (reg_prev > config->reg_defaults[i].reg)
|
||||
sort_defaults = true;
|
||||
|
||||
reg_prev = config->reg_defaults[i].reg;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cache_types); i++)
|
||||
if (cache_types[i]->type == map->cache_type)
|
||||
break;
|
||||
@@ -186,6 +194,13 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
|
||||
sizeof(*map->reg_defaults), GFP_KERNEL);
|
||||
if (!tmp_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* regcache_lookup_reg() bsearch()es this array */
|
||||
if (sort_defaults) {
|
||||
dev_warn(map->dev,
|
||||
"Driver needs fixing: Unsorted reg_defaults, sorting the copy\n");
|
||||
regcache_sort_defaults(tmp_buf, map->num_reg_defaults);
|
||||
}
|
||||
map->reg_defaults = tmp_buf;
|
||||
} else if (map->num_reg_defaults_raw) {
|
||||
count = regcache_count_cacheable_registers(map);
|
||||
@@ -727,14 +742,6 @@ unsigned int regcache_get_val(struct regmap *map, const void *base,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int regcache_default_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct reg_default *_a = a;
|
||||
const struct reg_default *_b = b;
|
||||
|
||||
return _a->reg - _b->reg;
|
||||
}
|
||||
|
||||
int regcache_lookup_reg(struct regmap *map, unsigned int reg)
|
||||
{
|
||||
struct reg_default key;
|
||||
@@ -744,7 +751,7 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
|
||||
key.def = 0;
|
||||
|
||||
r = bsearch(&key, map->reg_defaults, map->num_reg_defaults,
|
||||
sizeof(struct reg_default), regcache_default_cmp);
|
||||
sizeof(struct reg_default), regcache_defaults_cmp);
|
||||
|
||||
if (r)
|
||||
return r - map->reg_defaults;
|
||||
|
||||
Reference in New Issue
Block a user