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