aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-12-08 22:36:38 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-12-08 22:36:38 -0500
commitf4b98415953dcf85bac4ea0a2264a3ead4a7bcc4 (patch)
tree7195ababc3542402a794036b98d480b81a147c0f /arch/powerpc/kernel
parent46f5221049bb46b0188aad6b6dfab5dbc778be22 (diff)
parent6024ede9ba84aa1b891c2d6bc98eda07801235e5 (diff)
Merge branch 'nvram' into next
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/nvram_64.c481
1 files changed, 160 insertions, 321 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 9cf197f01e94..bb12b3248f13 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -34,15 +34,26 @@
34 34
35#undef DEBUG_NVRAM 35#undef DEBUG_NVRAM
36 36
37static struct nvram_partition * nvram_part; 37#define NVRAM_HEADER_LEN sizeof(struct nvram_header)
38static long nvram_error_log_index = -1; 38#define NVRAM_BLOCK_LEN NVRAM_HEADER_LEN
39static long nvram_error_log_size = 0; 39
40/* If change this size, then change the size of NVNAME_LEN */
41struct nvram_header {
42 unsigned char signature;
43 unsigned char checksum;
44 unsigned short length;
45 /* Terminating null required only for names < 12 chars. */
46 char name[12];
47};
40 48
41struct err_log_info { 49struct nvram_partition {
42 int error_type; 50 struct list_head partition;
43 unsigned int seq_num; 51 struct nvram_header header;
52 unsigned int index;
44}; 53};
45 54
55static LIST_HEAD(nvram_partitions);
56
46static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) 57static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
47{ 58{
48 int size; 59 int size;
@@ -186,14 +197,12 @@ static struct miscdevice nvram_dev = {
186#ifdef DEBUG_NVRAM 197#ifdef DEBUG_NVRAM
187static void __init nvram_print_partitions(char * label) 198static void __init nvram_print_partitions(char * label)
188{ 199{
189 struct list_head * p;
190 struct nvram_partition * tmp_part; 200 struct nvram_partition * tmp_part;
191 201
192 printk(KERN_WARNING "--------%s---------\n", label); 202 printk(KERN_WARNING "--------%s---------\n", label);
193 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); 203 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
194 list_for_each(p, &nvram_part->partition) { 204 list_for_each_entry(tmp_part, &nvram_partitions, partition) {
195 tmp_part = list_entry(p, struct nvram_partition, partition); 205 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12s\n",
196 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n",
197 tmp_part->index, tmp_part->header.signature, 206 tmp_part->index, tmp_part->header.signature,
198 tmp_part->header.checksum, tmp_part->header.length, 207 tmp_part->header.checksum, tmp_part->header.length,
199 tmp_part->header.name); 208 tmp_part->header.name);
@@ -228,95 +237,113 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
228 return c_sum; 237 return c_sum;
229} 238}
230 239
231static int __init nvram_remove_os_partition(void) 240/**
241 * nvram_remove_partition - Remove one or more partitions in nvram
242 * @name: name of the partition to remove, or NULL for a
243 * signature only match
244 * @sig: signature of the partition(s) to remove
245 */
246
247int __init nvram_remove_partition(const char *name, int sig)
232{ 248{
233 struct list_head *i; 249 struct nvram_partition *part, *prev, *tmp;
234 struct list_head *j;
235 struct nvram_partition * part;
236 struct nvram_partition * cur_part;
237 int rc; 250 int rc;
238 251
239 list_for_each(i, &nvram_part->partition) { 252 list_for_each_entry(part, &nvram_partitions, partition) {
240 part = list_entry(i, struct nvram_partition, partition); 253 if (part->header.signature != sig)
241 if (part->header.signature != NVRAM_SIG_OS)
242 continue; 254 continue;
243 255 if (name && strncmp(name, part->header.name, 12))
244 /* Make os partition a free partition */ 256 continue;
257
258 /* Make partition a free partition */
245 part->header.signature = NVRAM_SIG_FREE; 259 part->header.signature = NVRAM_SIG_FREE;
246 sprintf(part->header.name, "wwwwwwwwwwww"); 260 strncpy(part->header.name, "wwwwwwwwwwww", 12);
247 part->header.checksum = nvram_checksum(&part->header); 261 part->header.checksum = nvram_checksum(&part->header);
248
249 /* Merge contiguous free partitions backwards */
250 list_for_each_prev(j, &part->partition) {
251 cur_part = list_entry(j, struct nvram_partition, partition);
252 if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
253 break;
254 }
255
256 part->header.length += cur_part->header.length;
257 part->header.checksum = nvram_checksum(&part->header);
258 part->index = cur_part->index;
259
260 list_del(&cur_part->partition);
261 kfree(cur_part);
262 j = &part->partition; /* fixup our loop */
263 }
264
265 /* Merge contiguous free partitions forwards */
266 list_for_each(j, &part->partition) {
267 cur_part = list_entry(j, struct nvram_partition, partition);
268 if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
269 break;
270 }
271
272 part->header.length += cur_part->header.length;
273 part->header.checksum = nvram_checksum(&part->header);
274
275 list_del(&cur_part->partition);
276 kfree(cur_part);
277 j = &part->partition; /* fixup our loop */
278 }
279
280 rc = nvram_write_header(part); 262 rc = nvram_write_header(part);
281 if (rc <= 0) { 263 if (rc <= 0) {
282 printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc); 264 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
283 return rc; 265 return rc;
284 } 266 }
267 }
285 268
269 /* Merge contiguous ones */
270 prev = NULL;
271 list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
272 if (part->header.signature != NVRAM_SIG_FREE) {
273 prev = NULL;
274 continue;
275 }
276 if (prev) {
277 prev->header.length += part->header.length;
278 prev->header.checksum = nvram_checksum(&part->header);
279 rc = nvram_write_header(part);
280 if (rc <= 0) {
281 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
282 return rc;
283 }
284 list_del(&part->partition);
285 kfree(part);
286 } else
287 prev = part;
286 } 288 }
287 289
288 return 0; 290 return 0;
289} 291}
290 292
291/* nvram_create_os_partition 293/**
294 * nvram_create_partition - Create a partition in nvram
295 * @name: name of the partition to create
296 * @sig: signature of the partition to create
297 * @req_size: size of data to allocate in bytes
298 * @min_size: minimum acceptable size (0 means req_size)
292 * 299 *
293 * Create a OS linux partition to buffer error logs. 300 * Returns a negative error code or a positive nvram index
294 * Will create a partition starting at the first free 301 * of the beginning of the data area of the newly created
295 * space found if space has enough room. 302 * partition. If you provided a min_size smaller than req_size
303 * you need to query for the actual size yourself after the
304 * call using nvram_partition_get_size().
296 */ 305 */
297static int __init nvram_create_os_partition(void) 306loff_t __init nvram_create_partition(const char *name, int sig,
307 int req_size, int min_size)
298{ 308{
299 struct nvram_partition *part; 309 struct nvram_partition *part;
300 struct nvram_partition *new_part; 310 struct nvram_partition *new_part;
301 struct nvram_partition *free_part = NULL; 311 struct nvram_partition *free_part = NULL;
302 int seq_init[2] = { 0, 0 }; 312 static char nv_init_vals[16];
303 loff_t tmp_index; 313 loff_t tmp_index;
304 long size = 0; 314 long size = 0;
305 int rc; 315 int rc;
306 316
317 /* Convert sizes from bytes to blocks */
318 req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
319 min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
320
321 /* If no minimum size specified, make it the same as the
322 * requested size
323 */
324 if (min_size == 0)
325 min_size = req_size;
326 if (min_size > req_size)
327 return -EINVAL;
328
329 /* Now add one block to each for the header */
330 req_size += 1;
331 min_size += 1;
332
307 /* Find a free partition that will give us the maximum needed size 333 /* Find a free partition that will give us the maximum needed size
308 If can't find one that will give us the minimum size needed */ 334 If can't find one that will give us the minimum size needed */
309 list_for_each_entry(part, &nvram_part->partition, partition) { 335 list_for_each_entry(part, &nvram_partitions, partition) {
310 if (part->header.signature != NVRAM_SIG_FREE) 336 if (part->header.signature != NVRAM_SIG_FREE)
311 continue; 337 continue;
312 338
313 if (part->header.length >= NVRAM_MAX_REQ) { 339 if (part->header.length >= req_size) {
314 size = NVRAM_MAX_REQ; 340 size = req_size;
315 free_part = part; 341 free_part = part;
316 break; 342 break;
317 } 343 }
318 if (!size && part->header.length >= NVRAM_MIN_REQ) { 344 if (part->header.length > size &&
319 size = NVRAM_MIN_REQ; 345 part->header.length >= min_size) {
346 size = part->header.length;
320 free_part = part; 347 free_part = part;
321 } 348 }
322 } 349 }
@@ -326,136 +353,95 @@ static int __init nvram_create_os_partition(void)
326 /* Create our OS partition */ 353 /* Create our OS partition */
327 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); 354 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
328 if (!new_part) { 355 if (!new_part) {
329 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); 356 pr_err("nvram_create_os_partition: kmalloc failed\n");
330 return -ENOMEM; 357 return -ENOMEM;
331 } 358 }
332 359
333 new_part->index = free_part->index; 360 new_part->index = free_part->index;
334 new_part->header.signature = NVRAM_SIG_OS; 361 new_part->header.signature = sig;
335 new_part->header.length = size; 362 new_part->header.length = size;
336 strcpy(new_part->header.name, "ppc64,linux"); 363 strncpy(new_part->header.name, name, 12);
337 new_part->header.checksum = nvram_checksum(&new_part->header); 364 new_part->header.checksum = nvram_checksum(&new_part->header);
338 365
339 rc = nvram_write_header(new_part); 366 rc = nvram_write_header(new_part);
340 if (rc <= 0) { 367 if (rc <= 0) {
341 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 368 pr_err("nvram_create_os_partition: nvram_write_header "
342 "failed (%d)\n", rc);
343 return rc;
344 }
345
346 /* make sure and initialize to zero the sequence number and the error
347 type logged */
348 tmp_index = new_part->index + NVRAM_HEADER_LEN;
349 rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
350 if (rc <= 0) {
351 printk(KERN_ERR "nvram_create_os_partition: nvram_write "
352 "failed (%d)\n", rc); 369 "failed (%d)\n", rc);
353 return rc; 370 return rc;
354 } 371 }
355
356 nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
357 nvram_error_log_size = ((part->header.length - 1) *
358 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
359
360 list_add_tail(&new_part->partition, &free_part->partition); 372 list_add_tail(&new_part->partition, &free_part->partition);
361 373
362 if (free_part->header.length <= size) { 374 /* Adjust or remove the partition we stole the space from */
375 if (free_part->header.length > size) {
376 free_part->index += size * NVRAM_BLOCK_LEN;
377 free_part->header.length -= size;
378 free_part->header.checksum = nvram_checksum(&free_part->header);
379 rc = nvram_write_header(free_part);
380 if (rc <= 0) {
381 pr_err("nvram_create_os_partition: nvram_write_header "
382 "failed (%d)\n", rc);
383 return rc;
384 }
385 } else {
363 list_del(&free_part->partition); 386 list_del(&free_part->partition);
364 kfree(free_part); 387 kfree(free_part);
365 return 0;
366 } 388 }
367 389
368 /* Adjust the partition we stole the space from */ 390 /* Clear the new partition */
369 free_part->index += size * NVRAM_BLOCK_LEN; 391 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
370 free_part->header.length -= size; 392 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
371 free_part->header.checksum = nvram_checksum(&free_part->header); 393 tmp_index += NVRAM_BLOCK_LEN) {
372 394 rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
373 rc = nvram_write_header(free_part); 395 if (rc <= 0) {
374 if (rc <= 0) { 396 pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc);
375 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 397 return rc;
376 "failed (%d)\n", rc); 398 }
377 return rc;
378 } 399 }
379 400
380 return 0; 401 return new_part->index + NVRAM_HEADER_LEN;
381} 402}
382 403
383 404/**
384/* nvram_setup_partition 405 * nvram_get_partition_size - Get the data size of an nvram partition
385 * 406 * @data_index: This is the offset of the start of the data of
386 * This will setup the partition we need for buffering the 407 * the partition. The same value that is returned by
387 * error logs and cleanup partitions if needed. 408 * nvram_create_partition().
388 *
389 * The general strategy is the following:
390 * 1.) If there is ppc64,linux partition large enough then use it.
391 * 2.) If there is not a ppc64,linux partition large enough, search
392 * for a free partition that is large enough.
393 * 3.) If there is not a free partition large enough remove
394 * _all_ OS partitions and consolidate the space.
395 * 4.) Will first try getting a chunk that will satisfy the maximum
396 * error log size (NVRAM_MAX_REQ).
397 * 5.) If the max chunk cannot be allocated then try finding a chunk
398 * that will satisfy the minum needed (NVRAM_MIN_REQ).
399 */ 409 */
400static int __init nvram_setup_partition(void) 410int nvram_get_partition_size(loff_t data_index)
401{ 411{
402 struct list_head * p; 412 struct nvram_partition *part;
403 struct nvram_partition * part; 413
404 int rc; 414 list_for_each_entry(part, &nvram_partitions, partition) {
405 415 if (part->index + NVRAM_HEADER_LEN == data_index)
406 /* For now, we don't do any of this on pmac, until I 416 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
407 * have figured out if it's worth killing some unused stuffs 417 }
408 * in our nvram, as Apple defined partitions use pretty much 418 return -1;
409 * all of the space 419}
410 */
411 if (machine_is(powermac))
412 return -ENOSPC;
413
414 /* see if we have an OS partition that meets our needs.
415 will try getting the max we need. If not we'll delete
416 partitions and try again. */
417 list_for_each(p, &nvram_part->partition) {
418 part = list_entry(p, struct nvram_partition, partition);
419 if (part->header.signature != NVRAM_SIG_OS)
420 continue;
421 420
422 if (strcmp(part->header.name, "ppc64,linux"))
423 continue;
424 421
425 if (part->header.length >= NVRAM_MIN_REQ) { 422/**
426 /* found our partition */ 423 * nvram_find_partition - Find an nvram partition by signature and name
427 nvram_error_log_index = part->index + NVRAM_HEADER_LEN; 424 * @name: Name of the partition or NULL for any name
428 nvram_error_log_size = ((part->header.length - 1) * 425 * @sig: Signature to test against
429 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); 426 * @out_size: if non-NULL, returns the size of the data part of the partition
430 return 0; 427 */
428loff_t nvram_find_partition(const char *name, int sig, int *out_size)
429{
430 struct nvram_partition *p;
431
432 list_for_each_entry(p, &nvram_partitions, partition) {
433 if (p->header.signature == sig &&
434 (!name || !strncmp(p->header.name, name, 12))) {
435 if (out_size)
436 *out_size = (p->header.length - 1) *
437 NVRAM_BLOCK_LEN;
438 return p->index + NVRAM_HEADER_LEN;
431 } 439 }
432 } 440 }
433
434 /* try creating a partition with the free space we have */
435 rc = nvram_create_os_partition();
436 if (!rc) {
437 return 0;
438 }
439
440 /* need to free up some space */
441 rc = nvram_remove_os_partition();
442 if (rc) {
443 return rc;
444 }
445
446 /* create a partition in this new space */
447 rc = nvram_create_os_partition();
448 if (rc) {
449 printk(KERN_ERR "nvram_create_os_partition: Could not find a "
450 "NVRAM partition large enough\n");
451 return rc;
452 }
453
454 return 0; 441 return 0;
455} 442}
456 443
457 444int __init nvram_scan_partitions(void)
458static int __init nvram_scan_partitions(void)
459{ 445{
460 loff_t cur_index = 0; 446 loff_t cur_index = 0;
461 struct nvram_header phead; 447 struct nvram_header phead;
@@ -465,7 +451,7 @@ static int __init nvram_scan_partitions(void)
465 int total_size; 451 int total_size;
466 int err; 452 int err;
467 453
468 if (ppc_md.nvram_size == NULL) 454 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
469 return -ENODEV; 455 return -ENODEV;
470 total_size = ppc_md.nvram_size(); 456 total_size = ppc_md.nvram_size();
471 457
@@ -512,12 +498,16 @@ static int __init nvram_scan_partitions(void)
512 498
513 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); 499 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
514 tmp_part->index = cur_index; 500 tmp_part->index = cur_index;
515 list_add_tail(&tmp_part->partition, &nvram_part->partition); 501 list_add_tail(&tmp_part->partition, &nvram_partitions);
516 502
517 cur_index += phead.length * NVRAM_BLOCK_LEN; 503 cur_index += phead.length * NVRAM_BLOCK_LEN;
518 } 504 }
519 err = 0; 505 err = 0;
520 506
507#ifdef DEBUG_NVRAM
508 nvram_print_partitions("NVRAM Partitions");
509#endif
510
521 out: 511 out:
522 kfree(header); 512 kfree(header);
523 return err; 513 return err;
@@ -525,9 +515,10 @@ static int __init nvram_scan_partitions(void)
525 515
526static int __init nvram_init(void) 516static int __init nvram_init(void)
527{ 517{
528 int error;
529 int rc; 518 int rc;
530 519
520 BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
521
531 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) 522 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
532 return -ENODEV; 523 return -ENODEV;
533 524
@@ -537,29 +528,6 @@ static int __init nvram_init(void)
537 return rc; 528 return rc;
538 } 529 }
539 530
540 /* initialize our anchor for the nvram partition list */
541 nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
542 if (!nvram_part) {
543 printk(KERN_ERR "nvram_init: Failed kmalloc\n");
544 return -ENOMEM;
545 }
546 INIT_LIST_HEAD(&nvram_part->partition);
547
548 /* Get all the NVRAM partitions */
549 error = nvram_scan_partitions();
550 if (error) {
551 printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n");
552 return error;
553 }
554
555 if(nvram_setup_partition())
556 printk(KERN_WARNING "nvram_init: Could not find nvram partition"
557 " for nvram buffered error logging.\n");
558
559#ifdef DEBUG_NVRAM
560 nvram_print_partitions("NVRAM Partitions");
561#endif
562
563 return rc; 531 return rc;
564} 532}
565 533
@@ -568,135 +536,6 @@ void __exit nvram_cleanup(void)
568 misc_deregister( &nvram_dev ); 536 misc_deregister( &nvram_dev );
569} 537}
570 538
571
572#ifdef CONFIG_PPC_PSERIES
573
574/* nvram_write_error_log
575 *
576 * We need to buffer the error logs into nvram to ensure that we have
577 * the failure information to decode. If we have a severe error there
578 * is no way to guarantee that the OS or the machine is in a state to
579 * get back to user land and write the error to disk. For example if
580 * the SCSI device driver causes a Machine Check by writing to a bad
581 * IO address, there is no way of guaranteeing that the device driver
582 * is in any state that is would also be able to write the error data
583 * captured to disk, thus we buffer it in NVRAM for analysis on the
584 * next boot.
585 *
586 * In NVRAM the partition containing the error log buffer will looks like:
587 * Header (in bytes):
588 * +-----------+----------+--------+------------+------------------+
589 * | signature | checksum | length | name | data |
590 * |0 |1 |2 3|4 15|16 length-1|
591 * +-----------+----------+--------+------------+------------------+
592 *
593 * The 'data' section would look like (in bytes):
594 * +--------------+------------+-----------------------------------+
595 * | event_logged | sequence # | error log |
596 * |0 3|4 7|8 nvram_error_log_size-1|
597 * +--------------+------------+-----------------------------------+
598 *
599 * event_logged: 0 if event has not been logged to syslog, 1 if it has
600 * sequence #: The unique sequence # for each event. (until it wraps)
601 * error log: The error log from event_scan
602 */
603int nvram_write_error_log(char * buff, int length,
604 unsigned int err_type, unsigned int error_log_cnt)
605{
606 int rc;
607 loff_t tmp_index;
608 struct err_log_info info;
609
610 if (nvram_error_log_index == -1) {
611 return -ESPIPE;
612 }
613
614 if (length > nvram_error_log_size) {
615 length = nvram_error_log_size;
616 }
617
618 info.error_type = err_type;
619 info.seq_num = error_log_cnt;
620
621 tmp_index = nvram_error_log_index;
622
623 rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
624 if (rc <= 0) {
625 printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
626 return rc;
627 }
628
629 rc = ppc_md.nvram_write(buff, length, &tmp_index);
630 if (rc <= 0) {
631 printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
632 return rc;
633 }
634
635 return 0;
636}
637
638/* nvram_read_error_log
639 *
640 * Reads nvram for error log for at most 'length'
641 */
642int nvram_read_error_log(char * buff, int length,
643 unsigned int * err_type, unsigned int * error_log_cnt)
644{
645 int rc;
646 loff_t tmp_index;
647 struct err_log_info info;
648
649 if (nvram_error_log_index == -1)
650 return -1;
651
652 if (length > nvram_error_log_size)
653 length = nvram_error_log_size;
654
655 tmp_index = nvram_error_log_index;
656
657 rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
658 if (rc <= 0) {
659 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
660 return rc;
661 }
662
663 rc = ppc_md.nvram_read(buff, length, &tmp_index);
664 if (rc <= 0) {
665 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
666 return rc;
667 }
668
669 *error_log_cnt = info.seq_num;
670 *err_type = info.error_type;
671
672 return 0;
673}
674
675/* This doesn't actually zero anything, but it sets the event_logged
676 * word to tell that this event is safely in syslog.
677 */
678int nvram_clear_error_log(void)
679{
680 loff_t tmp_index;
681 int clear_word = ERR_FLAG_ALREADY_LOGGED;
682 int rc;
683
684 if (nvram_error_log_index == -1)
685 return -1;
686
687 tmp_index = nvram_error_log_index;
688
689 rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
690 if (rc <= 0) {
691 printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
692 return rc;
693 }
694
695 return 0;
696}
697
698#endif /* CONFIG_PPC_PSERIES */
699
700module_init(nvram_init); 539module_init(nvram_init);
701module_exit(nvram_cleanup); 540module_exit(nvram_cleanup);
702MODULE_LICENSE("GPL"); 541MODULE_LICENSE("GPL");