From: John Rose <johnrose@austin.ibm.com>
To: Michael Neuling <mikey@neuling.org>
Cc: External List <linuxppc-dev@ozlabs.org>,
Paul Mackerras <paulus@samba.org>
Subject: Re: [PATCH] powerpc: force 4k update_flash block and list sizes
Date: Tue, 07 Nov 2006 22:30:02 -0600 [thread overview]
Message-ID: <1162960202.14254.3.camel@sinatra.austin.ibm.com> (raw)
In-Reply-To: <20286.1162951582@neuling.org>
> kmem_cache_destroy doesn't return anything.
Good call! How's this:
The enablement of 64k pages on POWER platforms exposed a quirk in the RTAS
mechanism for updating firmware. RTAS assumes 4k for flash block and list
sizes, and use of any other sizes results in a failure.
This patch changes the rtas_flash module to force the use of 4k memory block
and list sizes when preparing and sending a firmware image to RTAS. It also
changes rtas_flash to use a slab cache to ensure 4k alignment of flash block
data. Such alignment is a documented requirement.
Signed-off-by: John Rose <johnrose@austin.ibm.com>
---
---
uf_4k-johnrose/arch/powerpc/kernel/rtas_flash.c | 52 +++++++++++++++++++-----
1 files changed, 42 insertions(+), 10 deletions(-)
diff -puN arch/powerpc/kernel/rtas_flash.c~uf_4k_alt2 arch/powerpc/kernel/rtas_flash.c
--- uf_4k/arch/powerpc/kernel/rtas_flash.c~uf_4k_alt2 2006-11-06 16:59:27.000000000 -0600
+++ uf_4k-johnrose/arch/powerpc/kernel/rtas_flash.c 2006-11-06 17:02:31.000000000 -0600
@@ -72,6 +72,10 @@
#define VALIDATE_BUF_SIZE 4096
#define RTAS_MSG_MAXLEN 64
+/* Quirk - RTAS requires 4k list length and block size */
+#define RTAS_BLKLIST_LENGTH 4096
+#define RTAS_BLK_SIZE 4096
+
struct flash_block {
char *data;
unsigned long length;
@@ -83,7 +87,7 @@ struct flash_block {
* into a version/length and translate the pointers
* to absolute.
*/
-#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block))
+#define FLASH_BLOCKS_PER_NODE ((RTAS_BLKLIST_LENGTH - 16) / sizeof(struct flash_block))
struct flash_block_list {
unsigned long num_blocks;
struct flash_block_list *next;
@@ -96,6 +100,9 @@ struct flash_block_list_header { /* just
static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
+/* Use slab cache to guarantee 4k alignment */
+static kmem_cache_t *flash_block_cache = NULL;
+
#define FLASH_BLOCK_LIST_VERSION (1UL)
/* Local copy of the flash block list.
@@ -153,7 +160,7 @@ static int flash_list_valid(struct flash
return FLASH_IMG_NULL_DATA;
}
block_size = f->blocks[i].length;
- if (block_size <= 0 || block_size > PAGE_SIZE) {
+ if (block_size <= 0 || block_size > RTAS_BLK_SIZE) {
return FLASH_IMG_BAD_LEN;
}
image_size += block_size;
@@ -177,9 +184,9 @@ static void free_flash_list(struct flash
while (f) {
for (i = 0; i < f->num_blocks; i++)
- free_page((unsigned long)(f->blocks[i].data));
+ kmem_cache_free(flash_block_cache, f->blocks[i].data);
next = f->next;
- free_page((unsigned long)f);
+ kmem_cache_free(flash_block_cache, f);
f = next;
}
}
@@ -278,6 +285,12 @@ static ssize_t rtas_flash_read(struct fi
return msglen;
}
+/* constructor for flash_block_cache */
+void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags)
+{
+ memset(ptr, 0, RTAS_BLK_SIZE);
+}
+
/* We could be much more efficient here. But to keep this function
* simple we allocate a page to the block list no matter how small the
* count is. If the system is low on memory it will be just as well
@@ -302,7 +315,7 @@ static ssize_t rtas_flash_write(struct f
* proc file
*/
if (uf->flist == NULL) {
- uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL);
+ uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
if (!uf->flist)
return -ENOMEM;
}
@@ -313,21 +326,21 @@ static ssize_t rtas_flash_write(struct f
next_free = fl->num_blocks;
if (next_free == FLASH_BLOCKS_PER_NODE) {
/* Need to allocate another block_list */
- fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL);
+ fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
if (!fl->next)
return -ENOMEM;
fl = fl->next;
next_free = 0;
}
- if (count > PAGE_SIZE)
- count = PAGE_SIZE;
- p = (char *)get_zeroed_page(GFP_KERNEL);
+ if (count > RTAS_BLK_SIZE)
+ count = RTAS_BLK_SIZE;
+ p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
if (!p)
return -ENOMEM;
if(copy_from_user(p, buffer, count)) {
- free_page((unsigned long)p);
+ kmem_cache_free(flash_block_cache, p);
return -EFAULT;
}
fl->blocks[next_free].data = p;
@@ -791,6 +804,16 @@ int __init rtas_flash_init(void)
goto cleanup;
rtas_flash_term_hook = rtas_flash_firmware;
+
+ flash_block_cache = kmem_cache_create("rtas_flash_cache",
+ RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
+ rtas_block_ctor, NULL);
+ if (!flash_block_cache) {
+ printk(KERN_ERR "%s: failed to create block cache\n",
+ __FUNCTION__);
+ rc = -ENOMEM;
+ goto cleanup;
+ }
return 0;
cleanup:
@@ -804,7 +827,16 @@ cleanup:
void __exit rtas_flash_cleanup(void)
{
+ int rc;
+
rtas_flash_term_hook = NULL;
+
+ if (flash_block_cache) {
+ rc = kmem_cache_destroy(flash_block_cache);
+ if (rc)
+ printk(KERN_WARNING "%s: cache memory leak\n",
+ __FUNCTION__);
+ }
remove_flash_pde(firmware_flash_pde);
remove_flash_pde(firmware_update_pde);
remove_flash_pde(validate_pde);
_
next prev parent reply other threads:[~2006-11-08 4:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-07 23:53 [PATCH] powerpc: force 4k update_flash block and list sizes John Rose
2006-11-08 2:06 ` Michael Neuling
2006-11-08 4:30 ` John Rose [this message]
2006-11-08 4:39 ` Michael Neuling
2006-11-08 16:07 ` John Rose
2006-11-08 4:41 ` Michael Ellerman
2006-11-08 9:28 ` Arnd Bergmann
2006-11-08 22:40 ` Michael Ellerman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1162960202.14254.3.camel@sinatra.austin.ibm.com \
--to=johnrose@austin.ibm.com \
--cc=linuxppc-dev@ozlabs.org \
--cc=mikey@neuling.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.