drivers/elog: treat offsets relative to start of mirror
Instead of treating offsets relative to after the header make the offsets relative to the in-memory mirror buffer. This simplifies the logic in that all offsets are treated the same. It also allows one to remove a global variable. BUG=chrome-os-partner:55932 Change-Id: I42491e05755d414562b02b6f9ae47f5c357d2f8a Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/16098 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
281c994ce2
commit
f41a9a6459
|
@ -45,16 +45,15 @@
|
||||||
* Static variables for ELOG state
|
* Static variables for ELOG state
|
||||||
*/
|
*/
|
||||||
static u16 total_size;
|
static u16 total_size;
|
||||||
static u16 log_size; /* excluding header */
|
|
||||||
static u32 flash_base;
|
static u32 flash_base;
|
||||||
static u16 full_threshold; /* from end of header */
|
static u16 full_threshold;
|
||||||
static u16 shrink_size; /* from end of header */
|
static u16 shrink_size;
|
||||||
|
|
||||||
static elog_area_state area_state;
|
static elog_area_state area_state;
|
||||||
static elog_header_state header_state;
|
static elog_header_state header_state;
|
||||||
static elog_event_buffer_state event_buffer_state;
|
static elog_event_buffer_state event_buffer_state;
|
||||||
|
|
||||||
static u16 next_event_offset; /* from end of header */
|
static u16 next_event_offset;
|
||||||
static u16 event_count;
|
static u16 event_count;
|
||||||
|
|
||||||
static struct spi_flash *elog_spi;
|
static struct spi_flash *elog_spi;
|
||||||
|
@ -72,16 +71,22 @@ static inline struct region_device *mirror_dev_get(void)
|
||||||
return &mirror_dev.rdev;
|
return &mirror_dev.rdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t elog_events_start(void)
|
||||||
|
{
|
||||||
|
/* Events are added directly after the header. */
|
||||||
|
return sizeof(struct elog_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t elog_events_total_space(void)
|
||||||
|
{
|
||||||
|
return total_size - elog_events_start();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to an event log header in the event data area
|
* Pointer to an event log header in the event data area
|
||||||
*/
|
*/
|
||||||
static struct event_header *elog_get_event_buffer(size_t offset, size_t size)
|
static struct event_header *elog_get_event_buffer(size_t offset, size_t size)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Events are appended relative to the end of the header. Update
|
|
||||||
* offset to include the header size.
|
|
||||||
*/
|
|
||||||
offset += sizeof(struct elog_header);
|
|
||||||
return rdev_mmap(mirror_dev_get(), offset, size);
|
return rdev_mmap(mirror_dev_get(), offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,17 +144,6 @@ static int elog_is_buffer_clear(size_t offset)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elog_event_buffer_is_clear(size_t offset)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Events are appended relative to the end of the header. Update
|
|
||||||
* offset to include the header size.
|
|
||||||
*/
|
|
||||||
offset += sizeof(struct elog_header);
|
|
||||||
|
|
||||||
return elog_is_buffer_clear(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the ELOG area has been initialized and is valid.
|
* Check that the ELOG area has been initialized and is valid.
|
||||||
*/
|
*/
|
||||||
|
@ -268,16 +262,6 @@ static void elog_flash_write(size_t offset, size_t size)
|
||||||
rdev_munmap(rdev, address);
|
rdev_munmap(rdev, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elog_append_event(size_t offset, size_t event_size)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Events are appended relative to the end of the header. Update
|
|
||||||
* offset to include the header size.
|
|
||||||
*/
|
|
||||||
offset += sizeof(struct elog_header);
|
|
||||||
elog_flash_write(offset, event_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Erase the first block specified in the address.
|
* Erase the first block specified in the address.
|
||||||
* Only handles flash area within a single flash block.
|
* Only handles flash area within a single flash block.
|
||||||
|
@ -300,7 +284,7 @@ static void elog_flash_erase(void)
|
||||||
static void elog_update_event_buffer_state(void)
|
static void elog_update_event_buffer_state(void)
|
||||||
{
|
{
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
u32 offset = 0;
|
size_t offset = elog_events_start();
|
||||||
|
|
||||||
elog_debug("elog_update_event_buffer_state()\n");
|
elog_debug("elog_update_event_buffer_state()\n");
|
||||||
|
|
||||||
|
@ -310,10 +294,9 @@ static void elog_update_event_buffer_state(void)
|
||||||
const size_t type_offset = offsetof(struct event_header, type);
|
const size_t type_offset = offsetof(struct event_header, type);
|
||||||
size_t len;
|
size_t len;
|
||||||
const size_t size = sizeof(type);
|
const size_t size = sizeof(type);
|
||||||
size_t abs_offset = offset + sizeof(struct elog_header);
|
|
||||||
|
|
||||||
if (rdev_readat(mirror_dev_get(), &type,
|
if (rdev_readat(mirror_dev_get(), &type,
|
||||||
abs_offset + type_offset, size) < 0) {
|
offset + type_offset, size) < 0) {
|
||||||
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -323,7 +306,7 @@ static void elog_update_event_buffer_state(void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Validate the event */
|
/* Validate the event */
|
||||||
len = elog_is_event_valid(abs_offset);
|
len = elog_is_event_valid(offset);
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
|
@ -336,7 +319,7 @@ static void elog_update_event_buffer_state(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the remaining buffer is empty */
|
/* Ensure the remaining buffer is empty */
|
||||||
if (!elog_event_buffer_is_clear(offset))
|
if (!elog_is_buffer_clear(offset))
|
||||||
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
|
|
||||||
/* Update ELOG state */
|
/* Update ELOG state */
|
||||||
|
@ -359,7 +342,7 @@ static void elog_scan_flash(void)
|
||||||
elog_spi->read(elog_spi, flash_base, total_size, mirror_buffer);
|
elog_spi->read(elog_spi, flash_base, total_size, mirror_buffer);
|
||||||
rdev_munmap(rdev, mirror_buffer);
|
rdev_munmap(rdev, mirror_buffer);
|
||||||
|
|
||||||
next_event_offset = 0;
|
next_event_offset = elog_events_start();
|
||||||
event_count = 0;
|
event_count = 0;
|
||||||
|
|
||||||
/* Check if the area is empty or not */
|
/* Check if the area is empty or not */
|
||||||
|
@ -412,14 +395,9 @@ static void elog_move_events_to_front(size_t offset, size_t size)
|
||||||
{
|
{
|
||||||
void *src;
|
void *src;
|
||||||
void *dest;
|
void *dest;
|
||||||
size_t start_offset = sizeof(struct elog_header);
|
size_t start_offset = elog_events_start();
|
||||||
const struct region_device *rdev = mirror_dev_get();
|
const struct region_device *rdev = mirror_dev_get();
|
||||||
|
|
||||||
/*
|
|
||||||
* Events are appended relative to the end of the header. Update
|
|
||||||
* offset to include the header size.
|
|
||||||
*/
|
|
||||||
offset += start_offset;
|
|
||||||
src = rdev_mmap(rdev, offset, size);
|
src = rdev_mmap(rdev, offset, size);
|
||||||
dest = rdev_mmap(rdev, start_offset, size);
|
dest = rdev_mmap(rdev, start_offset, size);
|
||||||
|
|
||||||
|
@ -454,7 +432,7 @@ static void elog_move_events_to_front(size_t offset, size_t size)
|
||||||
static int elog_shrink(void)
|
static int elog_shrink(void)
|
||||||
{
|
{
|
||||||
const struct region_device *rdev = mirror_dev_get();
|
const struct region_device *rdev = mirror_dev_get();
|
||||||
u16 offset = 0;
|
size_t offset = elog_events_start();
|
||||||
|
|
||||||
elog_debug("elog_shrink()\n");
|
elog_debug("elog_shrink()\n");
|
||||||
|
|
||||||
|
@ -464,21 +442,19 @@ static int elog_shrink(void)
|
||||||
const size_t size = sizeof(uint8_t);
|
const size_t size = sizeof(uint8_t);
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
size_t abs_offset = offset + sizeof(struct elog_header);
|
|
||||||
|
|
||||||
/* Next event has exceeded constraints */
|
/* Next event has exceeded constraints */
|
||||||
if (offset > shrink_size)
|
if (offset > shrink_size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (rdev_readat(rdev, &type, abs_offset + type_offset,
|
if (rdev_readat(rdev, &type, offset + type_offset, size) < 0)
|
||||||
size) < 0)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Reached the end of the area */
|
/* Reached the end of the area */
|
||||||
if (type == ELOG_TYPE_EOL)
|
if (type == ELOG_TYPE_EOL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (rdev_readat(rdev, &len, abs_offset + len_offset, size) < 0)
|
if (rdev_readat(rdev, &len, offset + len_offset, size) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
offset += len;
|
offset += len;
|
||||||
|
@ -497,7 +473,7 @@ static int elog_shrink(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add clear event */
|
/* Add clear event */
|
||||||
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, offset);
|
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, offset - elog_events_start());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -581,7 +557,7 @@ int elog_clear(void)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Log the clear event */
|
/* Log the clear event */
|
||||||
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, log_size);
|
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, elog_events_total_space());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -589,6 +565,7 @@ int elog_clear(void)
|
||||||
static void elog_find_flash(void)
|
static void elog_find_flash(void)
|
||||||
{
|
{
|
||||||
struct region r;
|
struct region r;
|
||||||
|
size_t reserved_space = ELOG_MIN_AVAILABLE_ENTRIES * MAX_EVENT_SIZE;
|
||||||
|
|
||||||
elog_debug("elog_find_flash()\n");
|
elog_debug("elog_find_flash()\n");
|
||||||
|
|
||||||
|
@ -602,8 +579,7 @@ static void elog_find_flash(void)
|
||||||
total_size = MIN(4*KiB, region_sz(&r));
|
total_size = MIN(4*KiB, region_sz(&r));
|
||||||
}
|
}
|
||||||
|
|
||||||
log_size = total_size - sizeof(struct elog_header);
|
full_threshold = total_size - reserved_space;
|
||||||
full_threshold = log_size - ELOG_MIN_AVAILABLE_ENTRIES * MAX_EVENT_SIZE;
|
|
||||||
shrink_size = MIN(total_size * ELOG_SHRINK_PERCENTAGE / 100,
|
shrink_size = MIN(total_size * ELOG_SHRINK_PERCENTAGE / 100,
|
||||||
full_threshold);
|
full_threshold);
|
||||||
}
|
}
|
||||||
|
@ -642,7 +618,7 @@ int elog_init(void)
|
||||||
} else if (total_size < sizeof(struct elog_header) + MAX_EVENT_SIZE) {
|
} else if (total_size < sizeof(struct elog_header) + MAX_EVENT_SIZE) {
|
||||||
printk(BIOS_ERR, "ELOG: Region too small to hold any events\n");
|
printk(BIOS_ERR, "ELOG: Region too small to hold any events\n");
|
||||||
return -1;
|
return -1;
|
||||||
} else if (log_size - shrink_size >= full_threshold) {
|
} else if (total_size - shrink_size >= full_threshold) {
|
||||||
printk(BIOS_ERR,
|
printk(BIOS_ERR,
|
||||||
"ELOG: SHRINK_PERCENTAGE set too small for MIN_AVAILABLE_ENTRIES\n");
|
"ELOG: SHRINK_PERCENTAGE set too small for MIN_AVAILABLE_ENTRIES\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -691,7 +667,8 @@ int elog_init(void)
|
||||||
|
|
||||||
/* Log a clear event if necessary */
|
/* Log a clear event if necessary */
|
||||||
if (event_count == 0)
|
if (event_count == 0)
|
||||||
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, log_size);
|
elog_add_event_word(ELOG_TYPE_LOG_CLEAR,
|
||||||
|
elog_events_total_space());
|
||||||
|
|
||||||
#if !defined(__SMM__)
|
#if !defined(__SMM__)
|
||||||
/* Log boot count event except in S3 resume */
|
/* Log boot count event except in S3 resume */
|
||||||
|
@ -793,7 +770,7 @@ void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
|
||||||
/* Update the ELOG state */
|
/* Update the ELOG state */
|
||||||
event_count++;
|
event_count++;
|
||||||
|
|
||||||
elog_append_event(next_event_offset, event_size);
|
elog_flash_write(next_event_offset, event_size);
|
||||||
|
|
||||||
next_event_offset += event_size;
|
next_event_offset += event_size;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue