diff options
Diffstat (limited to 'arch/powerpc/platforms/powernv/opal-flash.c')
| -rw-r--r-- | arch/powerpc/platforms/powernv/opal-flash.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c index dc487ff04704..5c21d9c07f45 100644 --- a/arch/powerpc/platforms/powernv/opal-flash.c +++ b/arch/powerpc/platforms/powernv/opal-flash.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
| 21 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
| 22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
| 23 | #include <linux/delay.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/opal.h> | 25 | #include <asm/opal.h> |
| 25 | 26 | ||
| @@ -130,7 +131,8 @@ static inline void opal_flash_validate(void) | |||
| 130 | { | 131 | { |
| 131 | long ret; | 132 | long ret; |
| 132 | void *buf = validate_flash_data.buf; | 133 | void *buf = validate_flash_data.buf; |
| 133 | __be32 size, result; | 134 | __be32 size = cpu_to_be32(validate_flash_data.buf_size); |
| 135 | __be32 result; | ||
| 134 | 136 | ||
| 135 | ret = opal_validate_flash(__pa(buf), &size, &result); | 137 | ret = opal_validate_flash(__pa(buf), &size, &result); |
| 136 | 138 | ||
| @@ -290,11 +292,6 @@ static int opal_flash_update(int op) | |||
| 290 | /* First entry address */ | 292 | /* First entry address */ |
| 291 | addr = __pa(list); | 293 | addr = __pa(list); |
| 292 | 294 | ||
| 293 | pr_alert("FLASH: Image is %u bytes\n", image_data.size); | ||
| 294 | pr_alert("FLASH: Image update requested\n"); | ||
| 295 | pr_alert("FLASH: Image will be updated during system reboot\n"); | ||
| 296 | pr_alert("FLASH: This will take several minutes. Do not power off!\n"); | ||
| 297 | |||
| 298 | flash: | 295 | flash: |
| 299 | rc = opal_update_flash(addr); | 296 | rc = opal_update_flash(addr); |
| 300 | 297 | ||
| @@ -302,6 +299,47 @@ invalid_img: | |||
| 302 | return rc; | 299 | return rc; |
| 303 | } | 300 | } |
| 304 | 301 | ||
| 302 | /* Return CPUs to OPAL before starting FW update */ | ||
| 303 | static void flash_return_cpu(void *info) | ||
| 304 | { | ||
| 305 | int cpu = smp_processor_id(); | ||
| 306 | |||
| 307 | if (!cpu_online(cpu)) | ||
| 308 | return; | ||
| 309 | |||
| 310 | /* Disable IRQ */ | ||
| 311 | hard_irq_disable(); | ||
| 312 | |||
| 313 | /* Return the CPU to OPAL */ | ||
| 314 | opal_return_cpu(); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* This gets called just before system reboots */ | ||
| 318 | void opal_flash_term_callback(void) | ||
| 319 | { | ||
| 320 | struct cpumask mask; | ||
| 321 | |||
| 322 | if (update_flash_data.status != FLASH_IMG_READY) | ||
| 323 | return; | ||
| 324 | |||
| 325 | pr_alert("FLASH: Flashing new firmware\n"); | ||
| 326 | pr_alert("FLASH: Image is %u bytes\n", image_data.size); | ||
| 327 | pr_alert("FLASH: Performing flash and reboot/shutdown\n"); | ||
| 328 | pr_alert("FLASH: This will take several minutes. Do not power off!\n"); | ||
| 329 | |||
| 330 | /* Small delay to help getting the above message out */ | ||
| 331 | msleep(500); | ||
| 332 | |||
| 333 | /* Return secondary CPUs to firmware */ | ||
| 334 | cpumask_copy(&mask, cpu_online_mask); | ||
| 335 | cpumask_clear_cpu(smp_processor_id(), &mask); | ||
| 336 | if (!cpumask_empty(&mask)) | ||
| 337 | smp_call_function_many(&mask, | ||
| 338 | flash_return_cpu, NULL, false); | ||
| 339 | /* Hard disable interrupts */ | ||
| 340 | hard_irq_disable(); | ||
| 341 | } | ||
| 342 | |||
| 305 | /* | 343 | /* |
| 306 | * Show candidate image status | 344 | * Show candidate image status |
| 307 | */ | 345 | */ |
