// SPDX-License-Identifier: GPL-2.0 // // Register cache access API - maple tree based cache // // Copyright 2023 Arm, Ltd // // Author: Mark Brown <broonie@kernel.org>
entry = kmalloc_array(last - index + 1, sizeof(*entry), map->alloc_flags); if (!entry) return -ENOMEM;
if (lower)
memcpy(entry, lower, lower_sz);
entry[reg - index] = val; if (upper)
memcpy(&entry[reg - index + 1], upper, upper_sz);
/* * This is safe because the regmap lock means the Maple lock * is redundant, but we need to take it due to lockdep asserts * in the maple tree code.
*/
mas_lock(&mas);
mas_set_range(&mas, index, last);
ret = mas_store_gfp(&mas, entry, map->alloc_flags);
mas_unlock(&mas);
if (ret == 0) {
kfree(lower);
kfree(upper);
}
return ret;
}
staticint regcache_maple_drop(struct regmap *map, unsignedint min, unsignedint max)
{ struct maple_tree *mt = map->cache;
MA_STATE(mas, mt, min, max); unsignedlong *entry, *lower, *upper; /* initialized to work around false-positive -Wuninitialized warning */ unsignedlong lower_index = 0, lower_last = 0; unsignedlong upper_index, upper_last; int ret = 0;
lower = NULL;
upper = NULL;
mas_lock(&mas);
mas_for_each(&mas, entry, max) { /* * This is safe because the regmap lock means the * Maple lock is redundant, but we need to take it due * to lockdep asserts in the maple tree code.
*/
mas_unlock(&mas);
/* Do we need to save any of this entry? */ if (mas.index < min) {
lower_index = mas.index;
lower_last = min -1;
lower = kmemdup_array(entry,
min - mas.index, sizeof(*lower),
map->alloc_flags); if (!lower) {
ret = -ENOMEM; goto out_unlocked;
}
}
if (mas.last > max) {
upper_index = max + 1;
upper_last = mas.last;
/* Insert new nodes with the saved data */ if (lower) {
mas_set_range(&mas, lower_index, lower_last);
ret = mas_store_gfp(&mas, lower, map->alloc_flags); if (ret != 0) goto out;
lower = NULL;
}
if (upper) {
mas_set_range(&mas, upper_index, upper_last);
ret = mas_store_gfp(&mas, upper, map->alloc_flags); if (ret != 0) goto out;
upper = NULL;
}
}
/* * Use a raw write if writing more than one register to a * device that supports raw writes to reduce transaction * overheads.
*/ if (max - min > 1 && regmap_can_raw_write(map)) {
buf = kmalloc_array(max - min, val_bytes, map->alloc_flags); if (!buf) {
ret = -ENOMEM; goto out;
}
/* Render the data for a raw write */ for (r = min; r < max; r++) {
regcache_set_val(map, buf, r - min,
entry[r - mas->index]);
}
if (!mt_external_lock(mt) && map->lock_key)
lockdep_set_class_and_subclass(&mt->ma_lock, map->lock_key, 1);
if (!map->num_reg_defaults) return 0;
range_start = 0;
/* Scan for ranges of contiguous registers */ for (i = 1; i < map->num_reg_defaults; i++) { if (map->reg_defaults[i].reg !=
map->reg_defaults[i - 1].reg + 1) {
ret = regcache_maple_insert_block(map, range_start,
i - 1); if (ret != 0) goto err;
range_start = i;
}
}
/* Add the last block */
ret = regcache_maple_insert_block(map, range_start,
map->num_reg_defaults - 1); if (ret != 0) goto err;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.