From patchwork Wed Jun 9 06:01:10 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milton Miller II X-Patchwork-Id: 55294 X-Patchwork-Delegate: benh@kernel.crashing.org Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 5CD3E100BF8 for ; Fri, 11 Jun 2010 17:26:37 +1000 (EST) Received: by ozlabs.org (Postfix) id 4C2C51007D3; Fri, 11 Jun 2010 17:12:21 +1000 (EST) Delivered-To: linuxppc-dev@ozlabs.org X-Greylist: delayed 1040 seconds by postgrey-1.32 at bilbo; Fri, 11 Jun 2010 17:12:20 EST Received: from mail4.comsite.net (mail4.comsite.net [205.238.176.238]) by ozlabs.org (Postfix) with ESMTP id A55AC1007D2 for ; Fri, 11 Jun 2010 17:12:20 +1000 (EST) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=71.20.111.250; Received: from mdm.bga.com (unverified [71.20.111.250]) by mail4.comsite.net (Comsite International, Inc. Advanced E-Mail Services) with ESMTP id 4782399-1844257 for multiple; Fri, 11 Jun 2010 01:55:07 -0500 From: Milton Miller Date: Wed, 9 Jun 2010 16:01:10 +1000 To: Anton Blanchard Subject: [PATCH] powerpc: rtas_flash needs to use rtas_data_buf Message-Id: <20100610-rtas-flash@mdm.bga.com> In-Reply-To: <20100610-reply@mdm.bga.com> References: <20100609060110.GM28295@kryten> <20100610-reply@mdm.bga.com> X-Originating-IP: 71.20.111.250 X-Mailman-Approved-At: Fri, 11 Jun 2010 17:26:30 +1000 Cc: linuxppc-dev@ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org When trying to flash a machine via the update_flash command, Anton received the following error: Restarting system. FLASH: kernel bug...flash list header addr above 4GB The code in question has a comment that the flash list should be in the kernel data and therefore under 4GB: /* NOTE: the "first" block list is a global var with no data * blocks in the kernel data segment. We do this because * we want to ensure this block_list addr is under 4GB. */ Unfortunately the Kconfig option is marked tristate which means the variable may not be in the kernel data and could be above 4GB. Instead of relying on the data segment being below 4GB, use the static data buffer allocated by the kernel for use by rtas. Since we don't use the header struct directly anymore, convert it to a simple pointer. Reported-By: Anton Blanchard Signed-Off-By: Milton Miller flist) { /* File was opened in write mode for a new flash attempt */ /* Clear saved list */ - if (rtas_firmware_flash_list.next) { - free_flash_list(rtas_firmware_flash_list.next); - rtas_firmware_flash_list.next = NULL; + if (rtas_firmware_flash_list) { + free_flash_list(rtas_firmware_flash_list); + rtas_firmware_flash_list = NULL; } if (uf->status != FLASH_AUTH) uf->status = flash_list_valid(uf->flist); if (uf->status == FLASH_IMG_READY) - rtas_firmware_flash_list.next = uf->flist; + rtas_firmware_flash_list = uf->flist; else free_flash_list(uf->flist); @@ -592,7 +589,7 @@ static void rtas_flash_firmware(int rebo unsigned long rtas_block_list; int i, status, update_token; - if (rtas_firmware_flash_list.next == NULL) + if (rtas_firmware_flash_list == NULL) return; /* nothing to do */ if (reboot_type != SYS_RESTART) { @@ -609,20 +606,25 @@ static void rtas_flash_firmware(int rebo return; } - /* NOTE: the "first" block list is a global var with no data - * blocks in the kernel data segment. We do this because - * we want to ensure this block_list addr is under 4GB. + /* + * NOTE: the "first" block must be under 4GB, so we create + * an entry with no data blocks in the reserved buffer in + * the kernel data segment. */ - rtas_firmware_flash_list.num_blocks = 0; - flist = (struct flash_block_list *)&rtas_firmware_flash_list; + spin_lock(&rtas_data_buf_lock); + flist = (struct rtas_flash_list *)&rtas_data_buf[0]; + flist.num_blocks = 0; + flist.next = rtas_firmware_flash_list; rtas_block_list = virt_to_abs(flist); if (rtas_block_list >= 4UL*1024*1024*1024) { printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); + spin_unlock(&rtas_data_buf_lock); return; } printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); /* Update the block_list in place. */ + rtas_firmware_flash_list = NULL; /* too hard to backout on error */ image_size = 0; for (f = flist; f; f = next) { /* Translate data addrs to absolute */ @@ -663,6 +665,7 @@ static void rtas_flash_firmware(int rebo printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); break; } + spin_unlock(&rtas_data_buf_lock); } static void remove_flash_pde(struct proc_dir_entry *dp)