Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7dea1ff3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull regmap debugfs optimisation fixes from Mark Brown:
 "The debugfs optimisations merged in v3.8 weren't my finest hour, there
  were a number of cases that the more complex algorithm made worse
  especially around the error handling.  This patch series should
  address those issues."

* tag 'regmap-debugfs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: debugfs: Make sure we store the last entry in the offset cache
  regmap: debugfs: Ensure a correct return value for empty caches
  regmap: debugfs: Discard the cache if we fail to allocate an entry
  regmap: debugfs: Fix check for block start in cached seeks
  regmap: debugfs: Fix attempts to read nonexistant register blocks
parents 2ac1e664 e8d6539c
Loading
Loading
Loading
Loading
+40 −13
Original line number Diff line number Diff line
@@ -56,6 +56,19 @@ static const struct file_operations regmap_name_fops = {
	.llseek = default_llseek,
};

static void regmap_debugfs_free_dump_cache(struct regmap *map)
{
	struct regmap_debugfs_off_cache *c;

	while (!list_empty(&map->debugfs_off_cache)) {
		c = list_first_entry(&map->debugfs_off_cache,
				     struct regmap_debugfs_off_cache,
				     list);
		list_del(&c->list);
		kfree(c);
	}
}

/*
 * Work out where the start offset maps into register numbers, bearing
 * in mind that we suppress hidden registers.
@@ -91,8 +104,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
			/* No cache entry?  Start a new one */
			if (!c) {
				c = kzalloc(sizeof(*c), GFP_KERNEL);
				if (!c)
					break;
				if (!c) {
					regmap_debugfs_free_dump_cache(map);
					return base;
				}
				c->min = p;
				c->base_reg = i;
			}
@@ -101,14 +116,34 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
		}
	}

	/* Close the last entry off if we didn't scan beyond it */
	if (c) {
		c->max = p - 1;
		list_add_tail(&c->list,
			      &map->debugfs_off_cache);
	} else {
		return base;
	}

	/*
	 * This should never happen; we return above if we fail to
	 * allocate and we should never be in this code if there are
	 * no registers at all.
	 */
	if (list_empty(&map->debugfs_off_cache)) {
		WARN_ON(list_empty(&map->debugfs_off_cache));
		return base;
	}

	/* Find the relevant block */
	list_for_each_entry(c, &map->debugfs_off_cache, list) {
		if (*pos >= c->min && *pos <= c->max) {
		if (from >= c->min && from <= c->max) {
			*pos = c->min;
			return c->base_reg;
		}

		ret = c->max;
		*pos = c->min;
		ret = c->base_reg;
	}

	return ret;
@@ -387,16 +422,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name)

void regmap_debugfs_exit(struct regmap *map)
{
	struct regmap_debugfs_off_cache *c;

	debugfs_remove_recursive(map->debugfs);
	while (!list_empty(&map->debugfs_off_cache)) {
		c = list_first_entry(&map->debugfs_off_cache,
				     struct regmap_debugfs_off_cache,
				     list);
		list_del(&c->list);
		kfree(c);
	}
	regmap_debugfs_free_dump_cache(map);
	kfree(map->debugfs_name);
}