[POWERPC] pseries: Force 4k update_flash block and list sizes

The enablement of 64k pages on pseries platforms exposed a bug 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,
even though PAPR does not specify any such requirement.

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. The rtas_flash function now uses a slab cache of 4k blocks with
4k alignment, rather than get_zeroed_page(), to allocate the memory for
the flash blocks and lists. The 4k alignment requirement is specified
in PAPR.

Signed-off-by: John Rose <johnrose@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by John Rose and committed by Paul Mackerras ae883cab 0091cf5a

+37 -10
+37 -10
arch/powerpc/kernel/rtas_flash.c
··· 72 72 #define VALIDATE_BUF_SIZE 4096 73 73 #define RTAS_MSG_MAXLEN 64 74 74 75 + /* Quirk - RTAS requires 4k list length and block size */ 76 + #define RTAS_BLKLIST_LENGTH 4096 77 + #define RTAS_BLK_SIZE 4096 78 + 75 79 struct flash_block { 76 80 char *data; 77 81 unsigned long length; ··· 87 83 * into a version/length and translate the pointers 88 84 * to absolute. 89 85 */ 90 - #define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) 86 + #define FLASH_BLOCKS_PER_NODE ((RTAS_BLKLIST_LENGTH - 16) / sizeof(struct flash_block)) 91 87 struct flash_block_list { 92 88 unsigned long num_blocks; 93 89 struct flash_block_list *next; ··· 99 95 }; 100 96 101 97 static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; 98 + 99 + /* Use slab cache to guarantee 4k alignment */ 100 + static kmem_cache_t *flash_block_cache = NULL; 102 101 103 102 #define FLASH_BLOCK_LIST_VERSION (1UL) 104 103 ··· 160 153 return FLASH_IMG_NULL_DATA; 161 154 } 162 155 block_size = f->blocks[i].length; 163 - if (block_size <= 0 || block_size > PAGE_SIZE) { 156 + if (block_size <= 0 || block_size > RTAS_BLK_SIZE) { 164 157 return FLASH_IMG_BAD_LEN; 165 158 } 166 159 image_size += block_size; ··· 184 177 185 178 while (f) { 186 179 for (i = 0; i < f->num_blocks; i++) 187 - free_page((unsigned long)(f->blocks[i].data)); 180 + kmem_cache_free(flash_block_cache, f->blocks[i].data); 188 181 next = f->next; 189 - free_page((unsigned long)f); 182 + kmem_cache_free(flash_block_cache, f); 190 183 f = next; 191 184 } 192 185 } ··· 285 278 return msglen; 286 279 } 287 280 281 + /* constructor for flash_block_cache */ 282 + void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) 283 + { 284 + memset(ptr, 0, RTAS_BLK_SIZE); 285 + } 286 + 288 287 /* We could be much more efficient here. But to keep this function 289 288 * simple we allocate a page to the block list no matter how small the 290 289 * count is. If the system is low on memory it will be just as well ··· 315 302 * proc file 316 303 */ 317 304 if (uf->flist == NULL) { 318 - uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); 305 + uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); 319 306 if (!uf->flist) 320 307 return -ENOMEM; 321 308 } ··· 326 313 next_free = fl->num_blocks; 327 314 if (next_free == FLASH_BLOCKS_PER_NODE) { 328 315 /* Need to allocate another block_list */ 329 - fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); 316 + fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); 330 317 if (!fl->next) 331 318 return -ENOMEM; 332 319 fl = fl->next; 333 320 next_free = 0; 334 321 } 335 322 336 - if (count > PAGE_SIZE) 337 - count = PAGE_SIZE; 338 - p = (char *)get_zeroed_page(GFP_KERNEL); 323 + if (count > RTAS_BLK_SIZE) 324 + count = RTAS_BLK_SIZE; 325 + p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); 339 326 if (!p) 340 327 return -ENOMEM; 341 328 342 329 if(copy_from_user(p, buffer, count)) { 343 - free_page((unsigned long)p); 330 + kmem_cache_free(flash_block_cache, p); 344 331 return -EFAULT; 345 332 } 346 333 fl->blocks[next_free].data = p; ··· 804 791 goto cleanup; 805 792 806 793 rtas_flash_term_hook = rtas_flash_firmware; 794 + 795 + flash_block_cache = kmem_cache_create("rtas_flash_cache", 796 + RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, 797 + rtas_block_ctor, NULL); 798 + if (!flash_block_cache) { 799 + printk(KERN_ERR "%s: failed to create block cache\n", 800 + __FUNCTION__); 801 + rc = -ENOMEM; 802 + goto cleanup; 803 + } 807 804 return 0; 808 805 809 806 cleanup: ··· 828 805 void __exit rtas_flash_cleanup(void) 829 806 { 830 807 rtas_flash_term_hook = NULL; 808 + 809 + if (flash_block_cache) 810 + kmem_cache_destroy(flash_block_cache); 811 + 831 812 remove_flash_pde(firmware_flash_pde); 832 813 remove_flash_pde(firmware_update_pde); 833 814 remove_flash_pde(validate_pde);