1
/* Copyright 2013-2014 IBM Corp.
3
* Licensed under the Apache License, Version 2.0 (the "License");
4
* you may not use this file except in compliance with the License.
5
* You may obtain a copy of the License at
7
* http://www.apache.org/licenses/LICENSE-2.0
9
* Unless required by applicable law or agreed to in writing, software
10
* distributed under the License is distributed on an "AS IS" BASIS,
11
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
/* This file contains the front end for OPAL error logging. It is used
18
* to construct a struct errorlog representing the event/error to be
19
* logged which is then passed to the platform specific backend to log
28
* Maximum number buffers that are pre-allocated
29
* to hold elogs that are reported on Sapphire and
32
#define ELOG_WRITE_MAX_RECORD 64
34
/* Platform Log ID as per the spec */
35
static uint32_t sapphire_elog_id = 0xB0000000;
36
/* Reserved for future use */
37
/* static uint32_t powernv_elog_id = 0xB1000000; */
39
/* Pool to allocate elog messages from */
40
static struct pool elog_pool;
41
static struct lock elog_lock = LOCK_UNLOCKED;
43
static bool elog_available = false;
45
static struct errorlog *get_write_buffer(int opal_event_severity)
53
if (opal_event_severity == OPAL_ERROR_PANIC)
54
buf = pool_get(&elog_pool, POOL_HIGH);
56
buf = pool_get(&elog_pool, POOL_NORMAL);
61
/* Reporting of error via struct errorlog */
62
struct errorlog *opal_elog_create(struct opal_err_info *e_info, uint32_t tag)
66
buf = get_write_buffer(e_info->sev);
68
buf->error_event_type = e_info->err_type;
69
buf->component_id = e_info->cmp_id;
70
buf->subsystem_id = e_info->subsystem;
71
buf->event_severity = e_info->sev;
72
buf->event_subtype = e_info->event_subtype;
73
buf->reason_code = e_info->reason_code;
74
buf->elog_origin = ORG_SAPPHIRE;
77
buf->plid = ++sapphire_elog_id;
80
/* Initialise the first user dump section */
81
log_add_section(buf, tag);
87
/* Add a new user data section to an existing error log */
88
void log_add_section(struct errorlog *buf, uint32_t tag)
90
size_t size = sizeof(struct elog_user_data_section) - 1;
91
struct elog_user_data_section *tmp;
94
prerror("ELOG: Cannot add user data section. "
95
"Buffer is invalid\n");
99
if ((buf->user_section_size + size) > OPAL_LOG_MAX_DUMP) {
100
prerror("ELOG: Size of dump data overruns buffer\n");
104
tmp = (struct elog_user_data_section *)(buf->user_data_dump +
105
buf->user_section_size);
106
/* Use DESC if no other tag provided */
107
tmp->tag = tag ? tag : 0x44455343;
110
buf->user_section_size += tmp->size;
111
buf->user_section_count++;
114
void opal_elog_complete(struct errorlog *buf, bool success)
117
printf("Unable to log error\n");
120
pool_free_object(&elog_pool, buf);
124
void log_commit(struct errorlog *elog)
131
if (platform.elog_commit) {
132
rc = platform.elog_commit(elog);
134
prerror("ELOG: Platform commit error %d\n", rc);
137
opal_elog_complete(elog, false);
140
void log_append_data(struct errorlog *buf, unsigned char *data, uint16_t size)
142
struct elog_user_data_section *section;
147
prerror("ELOG: Cannot update user data. Buffer is invalid\n");
151
if ((buf->user_section_size + size) > OPAL_LOG_MAX_DUMP) {
152
prerror("ELOG: Size of dump data overruns buffer\n");
156
/* Step through user sections to find latest dump section */
157
buffer = buf->user_data_dump;
158
n_sections = buf->user_section_count;
161
prerror("ELOG: User section invalid\n");
165
while (--n_sections) {
166
section = (struct elog_user_data_section *)buffer;
167
buffer += section->size;
170
section = (struct elog_user_data_section *)buffer;
171
buffer += section->size;
172
memcpy(buffer, data, size);
174
section->size += size;
175
buf->user_section_size += size;
178
void log_append_msg(struct errorlog *buf, const char *fmt, ...)
184
prerror("Tried to append log to NULL buffer\n");
189
vsnprintf(err_msg, sizeof(err_msg), fmt, list);
192
/* Log the error on to Sapphire console */
193
prerror("%s", err_msg);
195
log_append_data(buf, err_msg, strlen(err_msg));
198
void log_simple_error(struct opal_err_info *e_info, const char *fmt, ...)
200
struct errorlog *buf;
205
vsnprintf(err_msg, sizeof(err_msg), fmt, list);
208
/* Log the error on to Sapphire console */
209
prerror("%s", err_msg);
211
buf = opal_elog_create(e_info, 0);
213
prerror("ELOG: Error getting buffer to log error\n");
215
log_append_data(buf, err_msg, strlen(err_msg));
222
/* pre-allocate memory for records */
223
if (pool_init(&elog_pool, sizeof(struct errorlog), ELOG_WRITE_MAX_RECORD, 1))
224
return OPAL_RESOURCE;
226
elog_available = true;