aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/nvram_64.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-29 03:38:55 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-11-29 23:33:58 -0500
commite49e2e87235518c21b1f5228809209831e6169e7 (patch)
tree4c4db56f64fa796e87d693835cb14b4f31f6303b /arch/powerpc/kernel/nvram_64.c
parentcef0d5ad62ec6e0c8456b8f58e898aa3219311a5 (diff)
powerpc/nvram: Shuffle code around in nvram_create_partition()
This error log stuff is really pseries specific. As a first step we move the initialization of these variables to the caller of nvram_create_partition(), which is also slightly reorganized so we setup the free partition before we clear the new partition, so the chance of an error during clear leaving us with invalid headers is lessened. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/nvram_64.c')
-rw-r--r--arch/powerpc/kernel/nvram_64.c108
1 files changed, 62 insertions, 46 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 02737e68755..eabee7c6118 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -313,9 +313,15 @@ static int __init nvram_remove_os_partition(void)
313 * @sig: signature of the partition to create 313 * @sig: signature of the partition to create
314 * @req_size: size of data to allocate in bytes 314 * @req_size: size of data to allocate in bytes
315 * @min_size: minimum acceptable size (0 means req_size) 315 * @min_size: minimum acceptable size (0 means req_size)
316 *
317 * Returns a negative error code or a positive nvram index
318 * of the beginning of the data area of the newly created
319 * partition. If you provided a min_size smaller than req_size
320 * you need to query for the actual size yourself after the
321 * call using nvram_partition_get_size().
316 */ 322 */
317static int __init nvram_create_partition(const char *name, int sig, 323static loff_t __init nvram_create_partition(const char *name, int sig,
318 int req_size, int min_size) 324 int req_size, int min_size)
319{ 325{
320 struct nvram_partition *part; 326 struct nvram_partition *part;
321 struct nvram_partition *new_part; 327 struct nvram_partition *new_part;
@@ -334,6 +340,8 @@ static int __init nvram_create_partition(const char *name, int sig,
334 */ 340 */
335 if (min_size == 0) 341 if (min_size == 0)
336 min_size = req_size; 342 min_size = req_size;
343 if (min_size > req_size)
344 return -EINVAL;
337 345
338 /* Now add one block to each for the header */ 346 /* Now add one block to each for the header */
339 req_size += 1; 347 req_size += 1;
@@ -362,7 +370,7 @@ static int __init nvram_create_partition(const char *name, int sig,
362 /* Create our OS partition */ 370 /* Create our OS partition */
363 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); 371 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
364 if (!new_part) { 372 if (!new_part) {
365 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); 373 pr_err("nvram_create_os_partition: kmalloc failed\n");
366 return -ENOMEM; 374 return -ENOMEM;
367 } 375 }
368 376
@@ -374,12 +382,29 @@ static int __init nvram_create_partition(const char *name, int sig,
374 382
375 rc = nvram_write_header(new_part); 383 rc = nvram_write_header(new_part);
376 if (rc <= 0) { 384 if (rc <= 0) {
377 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 385 pr_err("nvram_create_os_partition: nvram_write_header "
378 "failed (%d)\n", rc); 386 "failed (%d)\n", rc);
379 return rc; 387 return rc;
380 } 388 }
389 list_add_tail(&new_part->partition, &free_part->partition);
390
391 /* Adjust or remove the partition we stole the space from */
392 if (free_part->header.length > size) {
393 free_part->index += size * NVRAM_BLOCK_LEN;
394 free_part->header.length -= size;
395 free_part->header.checksum = nvram_checksum(&free_part->header);
396 rc = nvram_write_header(free_part);
397 if (rc <= 0) {
398 pr_err("nvram_create_os_partition: nvram_write_header "
399 "failed (%d)\n", rc);
400 return rc;
401 }
402 } else {
403 list_del(&free_part->partition);
404 kfree(free_part);
405 }
381 406
382 /* Clear the partition */ 407 /* Clear the new partition */
383 for (tmp_index = new_part->index + NVRAM_HEADER_LEN; 408 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
384 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN); 409 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
385 tmp_index += NVRAM_BLOCK_LEN) { 410 tmp_index += NVRAM_BLOCK_LEN) {
@@ -390,31 +415,24 @@ static int __init nvram_create_partition(const char *name, int sig,
390 } 415 }
391 } 416 }
392 417
393 nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN; 418 return new_part->index + NVRAM_HEADER_LEN;
394 nvram_error_log_size = ((part->header.length - 1) * 419}
395 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
396
397 list_add_tail(&new_part->partition, &free_part->partition);
398
399 if (free_part->header.length <= size) {
400 list_del(&free_part->partition);
401 kfree(free_part);
402 return 0;
403 }
404 420
405 /* Adjust the partition we stole the space from */ 421/**
406 free_part->index += size * NVRAM_BLOCK_LEN; 422 * nvram_get_partition_size - Get the data size of an nvram partition
407 free_part->header.length -= size; 423 * @data_index: This is the offset of the start of the data of
408 free_part->header.checksum = nvram_checksum(&free_part->header); 424 * the partition. The same value that is returned by
425 * nvram_create_partition().
426 */
427static int nvram_get_partition_size(loff_t data_index)
428{
429 struct nvram_partition *part;
409 430
410 rc = nvram_write_header(free_part); 431 list_for_each_entry(part, &nvram_part->partition, partition) {
411 if (rc <= 0) { 432 if (part->index + NVRAM_HEADER_LEN == data_index)
412 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 433 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
413 "failed (%d)\n", rc);
414 return rc;
415 } 434 }
416 435 return -1;
417 return 0;
418} 436}
419 437
420 438
@@ -469,30 +487,28 @@ static int __init nvram_setup_partition(void)
469 } 487 }
470 488
471 /* try creating a partition with the free space we have */ 489 /* try creating a partition with the free space we have */
472 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS, 490 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
473 NVRAM_MAX_REQ, NVRAM_MIN_REQ); 491 NVRAM_MAX_REQ, NVRAM_MIN_REQ);
474 if (!rc) 492 if (rc < 0) {
475 return 0; 493 /* need to free up some space */
476 494 rc = nvram_remove_os_partition();
477 /* need to free up some space */ 495 if (rc)
478 rc = nvram_remove_os_partition(); 496 return rc;
479 if (rc) { 497 /* create a partition in this new space */
480 return rc; 498 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
481 } 499 NVRAM_MAX_REQ, NVRAM_MIN_REQ);
482 500 if (rc < 0) {
483 /* create a partition in this new space */ 501 pr_err("nvram_create_partition: Could not find"
484 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS, 502 " enough space in NVRAM for partition\n");
485 NVRAM_MAX_REQ, NVRAM_MIN_REQ); 503 return rc;
486 if (rc) { 504 }
487 printk(KERN_ERR "nvram_create_partition: Could not find a "
488 "NVRAM partition large enough\n");
489 return rc;
490 } 505 }
491 506
507 nvram_error_log_index = rc;
508 nvram_error_log_size = nvram_get_partition_size(rc) - sizeof(struct err_log_info);
492 return 0; 509 return 0;
493} 510}
494 511
495
496static int __init nvram_scan_partitions(void) 512static int __init nvram_scan_partitions(void)
497{ 513{
498 loff_t cur_index = 0; 514 loff_t cur_index = 0;