diff options
author | Tim Wawrzynczak <twawrzynczak@chromium.org> | 2020-08-25 16:49:45 -0600 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2020-08-31 06:38:09 +0000 |
commit | 299f3f834fe326d84b2e0e062b8f54196d657368 (patch) | |
tree | 0691d5aafca9246e61f4e9900ad05c129b71041c | |
parent | 668132a47c97f22631b021a580f694ea8680e927 (diff) |
fw_config: Add caching to successfully probed fields
Add a backing cache for all successfully probed fw_config fields that
originated as `probe` statements in the devicetree. This allows recall
of the `struct fw_config` which was probed.
BUG=b:161963281
TEST=tested with follower patch
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Change-Id: I0d014206a4ee6cc7592e12e704a7708652330eaf
Reviewed-on: https://review.coreboot.org/c/coreboot/+/44782
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
-rw-r--r-- | src/include/fw_config.h | 15 | ||||
-rw-r--r-- | src/lib/fw_config.c | 37 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/include/fw_config.h b/src/include/fw_config.h index d41afd6c5d..81980b93ae 100644 --- a/src/include/fw_config.h +++ b/src/include/fw_config.h @@ -40,6 +40,21 @@ struct fw_config { */ bool fw_config_probe(const struct fw_config *match); +/** + * fw_config_for_each_found() - Call a callback for each fw_config field found + * @cb: The callback function + * @arg: A context argument that is passed to the callback + */ +void fw_config_for_each_found(void (*cb)(const struct fw_config *config, void *arg), void *arg); + +/** + * fw_config_get_found() - Return a pointer to the fw_config struct for a given field. + * @field_mask: A field mask from static.h, e.g., FW_CONFIG_FIELD_FEATURE_MASK + * + * Return pointer to cached `struct fw_config` if successfully probed, otherwise NULL. +*/ +const struct fw_config *fw_config_get_found(uint32_t field_mask); + #else static inline bool fw_config_probe(const struct fw_config *match) diff --git a/src/lib/fw_config.c b/src/lib/fw_config.c index e97cfdc72a..fdfab0aab0 100644 --- a/src/lib/fw_config.c +++ b/src/lib/fw_config.c @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include <assert.h> #include <bootstate.h> #include <cbfs.h> #include <console/console.h> #include <device/device.h> #include <ec/google/chromeec/ec.h> #include <fw_config.h> +#include <lib.h> #include <stdbool.h> #include <stdint.h> @@ -66,6 +68,40 @@ bool fw_config_probe(const struct fw_config *match) } #if ENV_RAMSTAGE + +/* + * The maximum number of fw_config fields is limited by the 32-bit mask that is used to + * represent them. + */ +#define MAX_CACHE_ELEMENTS (8 * sizeof(uint32_t)) + +static const struct fw_config *cached_configs[MAX_CACHE_ELEMENTS]; + +static size_t probe_index(uint32_t mask) +{ + assert(mask); + return __ffs(mask); +} + +const struct fw_config *fw_config_get_found(uint32_t field_mask) +{ + const struct fw_config *config; + config = cached_configs[probe_index(field_mask)]; + if (config && config->mask == field_mask) + return config; + + return NULL; +} + +void fw_config_for_each_found(void (*cb)(const struct fw_config *config, void *arg), void *arg) +{ + size_t i; + + for (i = 0; i < MAX_CACHE_ELEMENTS; ++i) + if (cached_configs[i]) + cb(cached_configs[i], arg); +} + static void fw_config_init(void *unused) { struct device *dev; @@ -80,6 +116,7 @@ static void fw_config_init(void *unused) for (probe = dev->probe_list; probe && probe->mask != 0; probe++) { if (fw_config_probe(probe)) { match = true; + cached_configs[probe_index(probe->mask)] = probe; break; } } |