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>
This commit is contained in:
Tim Wawrzynczak 2020-08-25 16:49:45 -06:00 committed by Patrick Georgi
parent 668132a47c
commit 299f3f834f
2 changed files with 52 additions and 0 deletions

View File

@ -40,6 +40,21 @@ struct fw_config {
*/ */
bool fw_config_probe(const struct fw_config *match); 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 #else
static inline bool fw_config_probe(const struct fw_config *match) static inline bool fw_config_probe(const struct fw_config *match)

View File

@ -1,11 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <bootstate.h> #include <bootstate.h>
#include <cbfs.h> #include <cbfs.h>
#include <console/console.h> #include <console/console.h>
#include <device/device.h> #include <device/device.h>
#include <ec/google/chromeec/ec.h> #include <ec/google/chromeec/ec.h>
#include <fw_config.h> #include <fw_config.h>
#include <lib.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@ -66,6 +68,40 @@ bool fw_config_probe(const struct fw_config *match)
} }
#if ENV_RAMSTAGE #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) static void fw_config_init(void *unused)
{ {
struct device *dev; struct device *dev;
@ -80,6 +116,7 @@ static void fw_config_init(void *unused)
for (probe = dev->probe_list; probe && probe->mask != 0; probe++) { for (probe = dev->probe_list; probe && probe->mask != 0; probe++) {
if (fw_config_probe(probe)) { if (fw_config_probe(probe)) {
match = true; match = true;
cached_configs[probe_index(probe->mask)] = probe;
break; break;
} }
} }