aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/rtas_flash.c452
1 files changed, 204 insertions, 248 deletions
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index c642f0132988..5b770262c673 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -102,9 +102,10 @@ static struct kmem_cache *flash_block_cache = NULL;
102 102
103#define FLASH_BLOCK_LIST_VERSION (1UL) 103#define FLASH_BLOCK_LIST_VERSION (1UL)
104 104
105/* Local copy of the flash block list. 105/*
106 * We only allow one open of the flash proc file and create this 106 * Local copy of the flash block list.
107 * list as we go. The rtas_firmware_flash_list varable will be 107 *
108 * The rtas_firmware_flash_list varable will be
108 * set once the data is fully read. 109 * set once the data is fully read.
109 * 110 *
110 * For convenience as we build the list we use virtual addrs, 111 * For convenience as we build the list we use virtual addrs,
@@ -125,23 +126,23 @@ struct rtas_update_flash_t
125struct rtas_manage_flash_t 126struct rtas_manage_flash_t
126{ 127{
127 int status; /* Returned status */ 128 int status; /* Returned status */
128 unsigned int op; /* Reject or commit image */
129}; 129};
130 130
131/* Status int must be first member of struct */ 131/* Status int must be first member of struct */
132struct rtas_validate_flash_t 132struct rtas_validate_flash_t
133{ 133{
134 int status; /* Returned status */ 134 int status; /* Returned status */
135 char buf[VALIDATE_BUF_SIZE]; /* Candidate image buffer */ 135 char *buf; /* Candidate image buffer */
136 unsigned int buf_size; /* Size of image buf */ 136 unsigned int buf_size; /* Size of image buf */
137 unsigned int update_results; /* Update results token */ 137 unsigned int update_results; /* Update results token */
138}; 138};
139 139
140static DEFINE_SPINLOCK(flash_file_open_lock); 140static struct rtas_update_flash_t rtas_update_flash_data;
141static struct proc_dir_entry *firmware_flash_pde; 141static struct rtas_manage_flash_t rtas_manage_flash_data;
142static struct proc_dir_entry *firmware_update_pde; 142static struct rtas_validate_flash_t rtas_validate_flash_data;
143static struct proc_dir_entry *validate_pde; 143static DEFINE_MUTEX(rtas_update_flash_mutex);
144static struct proc_dir_entry *manage_pde; 144static DEFINE_MUTEX(rtas_manage_flash_mutex);
145static DEFINE_MUTEX(rtas_validate_flash_mutex);
145 146
146/* Do simple sanity checks on the flash image. */ 147/* Do simple sanity checks on the flash image. */
147static int flash_list_valid(struct flash_block_list *flist) 148static int flash_list_valid(struct flash_block_list *flist)
@@ -191,10 +192,10 @@ static void free_flash_list(struct flash_block_list *f)
191 192
192static int rtas_flash_release(struct inode *inode, struct file *file) 193static int rtas_flash_release(struct inode *inode, struct file *file)
193{ 194{
194 struct proc_dir_entry *dp = PDE(file_inode(file)); 195 struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
195 struct rtas_update_flash_t *uf; 196
196 197 mutex_lock(&rtas_update_flash_mutex);
197 uf = (struct rtas_update_flash_t *) dp->data; 198
198 if (uf->flist) { 199 if (uf->flist) {
199 /* File was opened in write mode for a new flash attempt */ 200 /* File was opened in write mode for a new flash attempt */
200 /* Clear saved list */ 201 /* Clear saved list */
@@ -214,13 +215,14 @@ static int rtas_flash_release(struct inode *inode, struct file *file)
214 uf->flist = NULL; 215 uf->flist = NULL;
215 } 216 }
216 217
217 atomic_dec(&dp->count); 218 mutex_unlock(&rtas_update_flash_mutex);
218 return 0; 219 return 0;
219} 220}
220 221
221static void get_flash_status_msg(int status, char *buf) 222static size_t get_flash_status_msg(int status, char *buf)
222{ 223{
223 char *msg; 224 const char *msg;
225 size_t len;
224 226
225 switch (status) { 227 switch (status) {
226 case FLASH_AUTH: 228 case FLASH_AUTH:
@@ -242,34 +244,51 @@ static void get_flash_status_msg(int status, char *buf)
242 msg = "ready: firmware image ready for flash on reboot\n"; 244 msg = "ready: firmware image ready for flash on reboot\n";
243 break; 245 break;
244 default: 246 default:
245 sprintf(buf, "error: unexpected status value %d\n", status); 247 return sprintf(buf, "error: unexpected status value %d\n",
246 return; 248 status);
247 } 249 }
248 250
249 strcpy(buf, msg); 251 len = strlen(msg);
252 memcpy(buf, msg, len + 1);
253 return len;
250} 254}
251 255
252/* Reading the proc file will show status (not the firmware contents) */ 256/* Reading the proc file will show status (not the firmware contents) */
253static ssize_t rtas_flash_read(struct file *file, char __user *buf, 257static ssize_t rtas_flash_read_msg(struct file *file, char __user *buf,
254 size_t count, loff_t *ppos) 258 size_t count, loff_t *ppos)
255{ 259{
256 struct proc_dir_entry *dp = PDE(file_inode(file)); 260 struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
257 struct rtas_update_flash_t *uf;
258 char msg[RTAS_MSG_MAXLEN]; 261 char msg[RTAS_MSG_MAXLEN];
262 size_t len;
263 int status;
259 264
260 uf = dp->data; 265 mutex_lock(&rtas_update_flash_mutex);
266 status = uf->status;
267 mutex_unlock(&rtas_update_flash_mutex);
261 268
262 if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) { 269 /* Read as text message */
263 get_flash_status_msg(uf->status, msg); 270 len = get_flash_status_msg(status, msg);
264 } else { /* FIRMWARE_UPDATE_NAME */ 271 return simple_read_from_buffer(buf, count, ppos, msg, len);
265 sprintf(msg, "%d\n", uf->status); 272}
266 } 273
274static ssize_t rtas_flash_read_num(struct file *file, char __user *buf,
275 size_t count, loff_t *ppos)
276{
277 struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
278 char msg[RTAS_MSG_MAXLEN];
279 int status;
267 280
281 mutex_lock(&rtas_update_flash_mutex);
282 status = uf->status;
283 mutex_unlock(&rtas_update_flash_mutex);
284
285 /* Read as number */
286 sprintf(msg, "%d\n", status);
268 return simple_read_from_buffer(buf, count, ppos, msg, strlen(msg)); 287 return simple_read_from_buffer(buf, count, ppos, msg, strlen(msg));
269} 288}
270 289
271/* constructor for flash_block_cache */ 290/* constructor for flash_block_cache */
272void rtas_block_ctor(void *ptr) 291static void rtas_block_ctor(void *ptr)
273{ 292{
274 memset(ptr, 0, RTAS_BLK_SIZE); 293 memset(ptr, 0, RTAS_BLK_SIZE);
275} 294}
@@ -282,16 +301,15 @@ void rtas_block_ctor(void *ptr)
282static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, 301static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
283 size_t count, loff_t *off) 302 size_t count, loff_t *off)
284{ 303{
285 struct proc_dir_entry *dp = PDE(file_inode(file)); 304 struct rtas_update_flash_t *const uf = &rtas_update_flash_data;
286 struct rtas_update_flash_t *uf;
287 char *p; 305 char *p;
288 int next_free; 306 int next_free, rc;
289 struct flash_block_list *fl; 307 struct flash_block_list *fl;
290 308
291 uf = (struct rtas_update_flash_t *) dp->data; 309 mutex_lock(&rtas_update_flash_mutex);
292 310
293 if (uf->status == FLASH_AUTH || count == 0) 311 if (uf->status == FLASH_AUTH || count == 0)
294 return count; /* discard data */ 312 goto out; /* discard data */
295 313
296 /* In the case that the image is not ready for flashing, the memory 314 /* In the case that the image is not ready for flashing, the memory
297 * allocated for the block list will be freed upon the release of the 315 * allocated for the block list will be freed upon the release of the
@@ -300,7 +318,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
300 if (uf->flist == NULL) { 318 if (uf->flist == NULL) {
301 uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); 319 uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
302 if (!uf->flist) 320 if (!uf->flist)
303 return -ENOMEM; 321 goto nomem;
304 } 322 }
305 323
306 fl = uf->flist; 324 fl = uf->flist;
@@ -311,7 +329,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
311 /* Need to allocate another block_list */ 329 /* Need to allocate another block_list */
312 fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); 330 fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
313 if (!fl->next) 331 if (!fl->next)
314 return -ENOMEM; 332 goto nomem;
315 fl = fl->next; 333 fl = fl->next;
316 next_free = 0; 334 next_free = 0;
317 } 335 }
@@ -320,52 +338,37 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
320 count = RTAS_BLK_SIZE; 338 count = RTAS_BLK_SIZE;
321 p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); 339 p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL);
322 if (!p) 340 if (!p)
323 return -ENOMEM; 341 goto nomem;
324 342
325 if(copy_from_user(p, buffer, count)) { 343 if(copy_from_user(p, buffer, count)) {
326 kmem_cache_free(flash_block_cache, p); 344 kmem_cache_free(flash_block_cache, p);
327 return -EFAULT; 345 rc = -EFAULT;
346 goto error;
328 } 347 }
329 fl->blocks[next_free].data = p; 348 fl->blocks[next_free].data = p;
330 fl->blocks[next_free].length = count; 349 fl->blocks[next_free].length = count;
331 fl->num_blocks++; 350 fl->num_blocks++;
332 351out:
352 mutex_unlock(&rtas_update_flash_mutex);
333 return count; 353 return count;
334}
335
336static int rtas_excl_open(struct inode *inode, struct file *file)
337{
338 struct proc_dir_entry *dp = PDE(inode);
339
340 /* Enforce exclusive open with use count of PDE */
341 spin_lock(&flash_file_open_lock);
342 if (atomic_read(&dp->count) > 2) {
343 spin_unlock(&flash_file_open_lock);
344 return -EBUSY;
345 }
346
347 atomic_inc(&dp->count);
348 spin_unlock(&flash_file_open_lock);
349
350 return 0;
351}
352
353static int rtas_excl_release(struct inode *inode, struct file *file)
354{
355 struct proc_dir_entry *dp = PDE(inode);
356 354
357 atomic_dec(&dp->count); 355nomem:
358 356 rc = -ENOMEM;
359 return 0; 357error:
358 mutex_unlock(&rtas_update_flash_mutex);
359 return rc;
360} 360}
361 361
362static void manage_flash(struct rtas_manage_flash_t *args_buf) 362/*
363 * Flash management routines.
364 */
365static void manage_flash(struct rtas_manage_flash_t *args_buf, unsigned int op)
363{ 366{
364 s32 rc; 367 s32 rc;
365 368
366 do { 369 do {
367 rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 370 rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 1,
368 1, NULL, args_buf->op); 371 NULL, op);
369 } while (rtas_busy_delay(rc)); 372 } while (rtas_busy_delay(rc));
370 373
371 args_buf->status = rc; 374 args_buf->status = rc;
@@ -374,55 +377,62 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf)
374static ssize_t manage_flash_read(struct file *file, char __user *buf, 377static ssize_t manage_flash_read(struct file *file, char __user *buf,
375 size_t count, loff_t *ppos) 378 size_t count, loff_t *ppos)
376{ 379{
377 struct proc_dir_entry *dp = PDE(file_inode(file)); 380 struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;
378 struct rtas_manage_flash_t *args_buf;
379 char msg[RTAS_MSG_MAXLEN]; 381 char msg[RTAS_MSG_MAXLEN];
380 int msglen; 382 int msglen, status;
381 383
382 args_buf = dp->data; 384 mutex_lock(&rtas_manage_flash_mutex);
383 if (args_buf == NULL) 385 status = args_buf->status;
384 return 0; 386 mutex_unlock(&rtas_manage_flash_mutex);
385
386 msglen = sprintf(msg, "%d\n", args_buf->status);
387 387
388 msglen = sprintf(msg, "%d\n", status);
388 return simple_read_from_buffer(buf, count, ppos, msg, msglen); 389 return simple_read_from_buffer(buf, count, ppos, msg, msglen);
389} 390}
390 391
391static ssize_t manage_flash_write(struct file *file, const char __user *buf, 392static ssize_t manage_flash_write(struct file *file, const char __user *buf,
392 size_t count, loff_t *off) 393 size_t count, loff_t *off)
393{ 394{
394 struct proc_dir_entry *dp = PDE(file_inode(file)); 395 struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;
395 struct rtas_manage_flash_t *args_buf; 396 static const char reject_str[] = "0";
396 const char reject_str[] = "0"; 397 static const char commit_str[] = "1";
397 const char commit_str[] = "1";
398 char stkbuf[10]; 398 char stkbuf[10];
399 int op; 399 int op, rc;
400
401 mutex_lock(&rtas_manage_flash_mutex);
400 402
401 args_buf = (struct rtas_manage_flash_t *) dp->data;
402 if ((args_buf->status == MANAGE_AUTH) || (count == 0)) 403 if ((args_buf->status == MANAGE_AUTH) || (count == 0))
403 return count; 404 goto out;
404 405
405 op = -1; 406 op = -1;
406 if (buf) { 407 if (buf) {
407 if (count > 9) count = 9; 408 if (count > 9) count = 9;
408 if (copy_from_user (stkbuf, buf, count)) { 409 rc = -EFAULT;
409 return -EFAULT; 410 if (copy_from_user (stkbuf, buf, count))
410 } 411 goto error;
411 if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0) 412 if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0)
412 op = RTAS_REJECT_TMP_IMG; 413 op = RTAS_REJECT_TMP_IMG;
413 else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0) 414 else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0)
414 op = RTAS_COMMIT_TMP_IMG; 415 op = RTAS_COMMIT_TMP_IMG;
415 } 416 }
416 417
417 if (op == -1) /* buf is empty, or contains invalid string */ 418 if (op == -1) { /* buf is empty, or contains invalid string */
418 return -EINVAL; 419 rc = -EINVAL;
419 420 goto error;
420 args_buf->op = op; 421 }
421 manage_flash(args_buf);
422 422
423 manage_flash(args_buf, op);
424out:
425 mutex_unlock(&rtas_manage_flash_mutex);
423 return count; 426 return count;
427
428error:
429 mutex_unlock(&rtas_manage_flash_mutex);
430 return rc;
424} 431}
425 432
433/*
434 * Validation routines.
435 */
426static void validate_flash(struct rtas_validate_flash_t *args_buf) 436static void validate_flash(struct rtas_validate_flash_t *args_buf)
427{ 437{
428 int token = rtas_token("ibm,validate-flash-image"); 438 int token = rtas_token("ibm,validate-flash-image");
@@ -462,14 +472,14 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
462static ssize_t validate_flash_read(struct file *file, char __user *buf, 472static ssize_t validate_flash_read(struct file *file, char __user *buf,
463 size_t count, loff_t *ppos) 473 size_t count, loff_t *ppos)
464{ 474{
465 struct proc_dir_entry *dp = PDE(file_inode(file)); 475 struct rtas_validate_flash_t *const args_buf =
466 struct rtas_validate_flash_t *args_buf; 476 &rtas_validate_flash_data;
467 char msg[RTAS_MSG_MAXLEN]; 477 char msg[RTAS_MSG_MAXLEN];
468 int msglen; 478 int msglen;
469 479
470 args_buf = dp->data; 480 mutex_lock(&rtas_validate_flash_mutex);
471
472 msglen = get_validate_flash_msg(args_buf, msg); 481 msglen = get_validate_flash_msg(args_buf, msg);
482 mutex_unlock(&rtas_validate_flash_mutex);
473 483
474 return simple_read_from_buffer(buf, count, ppos, msg, msglen); 484 return simple_read_from_buffer(buf, count, ppos, msg, msglen);
475} 485}
@@ -477,24 +487,18 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,
477static ssize_t validate_flash_write(struct file *file, const char __user *buf, 487static ssize_t validate_flash_write(struct file *file, const char __user *buf,
478 size_t count, loff_t *off) 488 size_t count, loff_t *off)
479{ 489{
480 struct proc_dir_entry *dp = PDE(file_inode(file)); 490 struct rtas_validate_flash_t *const args_buf =
481 struct rtas_validate_flash_t *args_buf; 491 &rtas_validate_flash_data;
482 int rc; 492 int rc;
483 493
484 args_buf = (struct rtas_validate_flash_t *) dp->data; 494 mutex_lock(&rtas_validate_flash_mutex);
485
486 if (dp->data == NULL) {
487 dp->data = kmalloc(sizeof(struct rtas_validate_flash_t),
488 GFP_KERNEL);
489 if (dp->data == NULL)
490 return -ENOMEM;
491 }
492 495
493 /* We are only interested in the first 4K of the 496 /* We are only interested in the first 4K of the
494 * candidate image */ 497 * candidate image */
495 if ((*off >= VALIDATE_BUF_SIZE) || 498 if ((*off >= VALIDATE_BUF_SIZE) ||
496 (args_buf->status == VALIDATE_AUTH)) { 499 (args_buf->status == VALIDATE_AUTH)) {
497 *off += count; 500 *off += count;
501 mutex_unlock(&rtas_validate_flash_mutex);
498 return count; 502 return count;
499 } 503 }
500 504
@@ -517,31 +521,29 @@ static ssize_t validate_flash_write(struct file *file, const char __user *buf,
517 *off += count; 521 *off += count;
518 rc = count; 522 rc = count;
519done: 523done:
520 if (rc < 0) { 524 mutex_unlock(&rtas_validate_flash_mutex);
521 kfree(dp->data);
522 dp->data = NULL;
523 }
524 return rc; 525 return rc;
525} 526}
526 527
527static int validate_flash_release(struct inode *inode, struct file *file) 528static int validate_flash_release(struct inode *inode, struct file *file)
528{ 529{
529 struct proc_dir_entry *dp = PDE(file_inode(file)); 530 struct rtas_validate_flash_t *const args_buf =
530 struct rtas_validate_flash_t *args_buf; 531 &rtas_validate_flash_data;
531 532
532 args_buf = (struct rtas_validate_flash_t *) dp->data; 533 mutex_lock(&rtas_validate_flash_mutex);
533 534
534 if (args_buf->status == VALIDATE_READY) { 535 if (args_buf->status == VALIDATE_READY) {
535 args_buf->buf_size = VALIDATE_BUF_SIZE; 536 args_buf->buf_size = VALIDATE_BUF_SIZE;
536 validate_flash(args_buf); 537 validate_flash(args_buf);
537 } 538 }
538 539
539 /* The matching atomic_inc was in rtas_excl_open() */ 540 mutex_unlock(&rtas_validate_flash_mutex);
540 atomic_dec(&dp->count);
541
542 return 0; 541 return 0;
543} 542}
544 543
544/*
545 * On-reboot flash update applicator.
546 */
545static void rtas_flash_firmware(int reboot_type) 547static void rtas_flash_firmware(int reboot_type)
546{ 548{
547 unsigned long image_size; 549 unsigned long image_size;
@@ -634,75 +636,57 @@ static void rtas_flash_firmware(int reboot_type)
634 spin_unlock(&rtas_data_buf_lock); 636 spin_unlock(&rtas_data_buf_lock);
635} 637}
636 638
637static void remove_flash_pde(struct proc_dir_entry *dp) 639/*
638{ 640 * Manifest of proc files to create
639 if (dp) { 641 */
640 kfree(dp->data); 642struct rtas_flash_file {
641 remove_proc_entry(dp->name, dp->parent); 643 const char *filename;
642 } 644 const char *rtas_call_name;
643}
644
645static int initialize_flash_pde_data(const char *rtas_call_name,
646 size_t buf_size,
647 struct proc_dir_entry *dp)
648{
649 int *status; 645 int *status;
650 int token; 646 const struct file_operations fops;
651
652 dp->data = kzalloc(buf_size, GFP_KERNEL);
653 if (dp->data == NULL)
654 return -ENOMEM;
655
656 /*
657 * This code assumes that the status int is the first member of the
658 * struct
659 */
660 status = (int *) dp->data;
661 token = rtas_token(rtas_call_name);
662 if (token == RTAS_UNKNOWN_SERVICE)
663 *status = FLASH_AUTH;
664 else
665 *status = FLASH_NO_OP;
666
667 return 0;
668}
669
670static struct proc_dir_entry *create_flash_pde(const char *filename,
671 const struct file_operations *fops)
672{
673 return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops);
674}
675
676static const struct file_operations rtas_flash_operations = {
677 .owner = THIS_MODULE,
678 .read = rtas_flash_read,
679 .write = rtas_flash_write,
680 .open = rtas_excl_open,
681 .release = rtas_flash_release,
682 .llseek = default_llseek,
683};
684
685static const struct file_operations manage_flash_operations = {
686 .owner = THIS_MODULE,
687 .read = manage_flash_read,
688 .write = manage_flash_write,
689 .open = rtas_excl_open,
690 .release = rtas_excl_release,
691 .llseek = default_llseek,
692}; 647};
693 648
694static const struct file_operations validate_flash_operations = { 649static const struct rtas_flash_file rtas_flash_files[] = {
695 .owner = THIS_MODULE, 650 {
696 .read = validate_flash_read, 651 .filename = "powerpc/rtas/" FIRMWARE_FLASH_NAME,
697 .write = validate_flash_write, 652 .rtas_call_name = "ibm,update-flash-64-and-reboot",
698 .open = rtas_excl_open, 653 .status = &rtas_update_flash_data.status,
699 .release = validate_flash_release, 654 .fops.read = rtas_flash_read_msg,
700 .llseek = default_llseek, 655 .fops.write = rtas_flash_write,
656 .fops.release = rtas_flash_release,
657 .fops.llseek = default_llseek,
658 },
659 {
660 .filename = "powerpc/rtas/" FIRMWARE_UPDATE_NAME,
661 .rtas_call_name = "ibm,update-flash-64-and-reboot",
662 .status = &rtas_update_flash_data.status,
663 .fops.read = rtas_flash_read_num,
664 .fops.write = rtas_flash_write,
665 .fops.release = rtas_flash_release,
666 .fops.llseek = default_llseek,
667 },
668 {
669 .filename = "powerpc/rtas/" VALIDATE_FLASH_NAME,
670 .rtas_call_name = "ibm,validate-flash-image",
671 .status = &rtas_validate_flash_data.status,
672 .fops.read = validate_flash_read,
673 .fops.write = validate_flash_write,
674 .fops.release = validate_flash_release,
675 .fops.llseek = default_llseek,
676 },
677 {
678 .filename = "powerpc/rtas/" MANAGE_FLASH_NAME,
679 .rtas_call_name = "ibm,manage-flash-image",
680 .status = &rtas_manage_flash_data.status,
681 .fops.read = manage_flash_read,
682 .fops.write = manage_flash_write,
683 .fops.llseek = default_llseek,
684 }
701}; 685};
702 686
703static int __init rtas_flash_init(void) 687static int __init rtas_flash_init(void)
704{ 688{
705 int rc; 689 int i;
706 690
707 if (rtas_token("ibm,update-flash-64-and-reboot") == 691 if (rtas_token("ibm,update-flash-64-and-reboot") ==
708 RTAS_UNKNOWN_SERVICE) { 692 RTAS_UNKNOWN_SERVICE) {
@@ -710,93 +694,65 @@ static int __init rtas_flash_init(void)
710 return 1; 694 return 1;
711 } 695 }
712 696
713 firmware_flash_pde = create_flash_pde("powerpc/rtas/" 697 rtas_validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
714 FIRMWARE_FLASH_NAME, 698 if (!rtas_validate_flash_data.buf)
715 &rtas_flash_operations); 699 return -ENOMEM;
716 if (firmware_flash_pde == NULL) {
717 rc = -ENOMEM;
718 goto cleanup;
719 }
720 700
721 rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", 701 flash_block_cache = kmem_cache_create("rtas_flash_cache",
722 sizeof(struct rtas_update_flash_t), 702 RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
723 firmware_flash_pde); 703 rtas_block_ctor);
724 if (rc != 0) 704 if (!flash_block_cache) {
725 goto cleanup; 705 printk(KERN_ERR "%s: failed to create block cache\n",
726 706 __func__);
727 firmware_update_pde = create_flash_pde("powerpc/rtas/" 707 goto enomem_buf;
728 FIRMWARE_UPDATE_NAME,
729 &rtas_flash_operations);
730 if (firmware_update_pde == NULL) {
731 rc = -ENOMEM;
732 goto cleanup;
733 } 708 }
734 709
735 rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", 710 for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) {
736 sizeof(struct rtas_update_flash_t), 711 const struct rtas_flash_file *f = &rtas_flash_files[i];
737 firmware_update_pde); 712 int token;
738 if (rc != 0)
739 goto cleanup;
740
741 validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME,
742 &validate_flash_operations);
743 if (validate_pde == NULL) {
744 rc = -ENOMEM;
745 goto cleanup;
746 }
747 713
748 rc = initialize_flash_pde_data("ibm,validate-flash-image", 714 if (!proc_create(f->filename, S_IRUSR | S_IWUSR, NULL, &f->fops))
749 sizeof(struct rtas_validate_flash_t), 715 goto enomem;
750 validate_pde);
751 if (rc != 0)
752 goto cleanup;
753
754 manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME,
755 &manage_flash_operations);
756 if (manage_pde == NULL) {
757 rc = -ENOMEM;
758 goto cleanup;
759 }
760 716
761 rc = initialize_flash_pde_data("ibm,manage-flash-image", 717 /*
762 sizeof(struct rtas_manage_flash_t), 718 * This code assumes that the status int is the first member of the
763 manage_pde); 719 * struct
764 if (rc != 0) 720 */
765 goto cleanup; 721 token = rtas_token(f->rtas_call_name);
722 if (token == RTAS_UNKNOWN_SERVICE)
723 *f->status = FLASH_AUTH;
724 else
725 *f->status = FLASH_NO_OP;
726 }
766 727
767 rtas_flash_term_hook = rtas_flash_firmware; 728 rtas_flash_term_hook = rtas_flash_firmware;
768
769 flash_block_cache = kmem_cache_create("rtas_flash_cache",
770 RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
771 rtas_block_ctor);
772 if (!flash_block_cache) {
773 printk(KERN_ERR "%s: failed to create block cache\n",
774 __func__);
775 rc = -ENOMEM;
776 goto cleanup;
777 }
778 return 0; 729 return 0;
779 730
780cleanup: 731enomem:
781 remove_flash_pde(firmware_flash_pde); 732 while (--i >= 0) {
782 remove_flash_pde(firmware_update_pde); 733 const struct rtas_flash_file *f = &rtas_flash_files[i];
783 remove_flash_pde(validate_pde); 734 remove_proc_entry(f->filename, NULL);
784 remove_flash_pde(manage_pde); 735 }
785 736
786 return rc; 737 kmem_cache_destroy(flash_block_cache);
738enomem_buf:
739 kfree(rtas_validate_flash_data.buf);
740 return -ENOMEM;
787} 741}
788 742
789static void __exit rtas_flash_cleanup(void) 743static void __exit rtas_flash_cleanup(void)
790{ 744{
745 int i;
746
791 rtas_flash_term_hook = NULL; 747 rtas_flash_term_hook = NULL;
792 748
793 if (flash_block_cache) 749 for (i = 0; i < ARRAY_SIZE(rtas_flash_files); i++) {
794 kmem_cache_destroy(flash_block_cache); 750 const struct rtas_flash_file *f = &rtas_flash_files[i];
751 remove_proc_entry(f->filename, NULL);
752 }
795 753
796 remove_flash_pde(firmware_flash_pde); 754 kmem_cache_destroy(flash_block_cache);
797 remove_flash_pde(firmware_update_pde); 755 kfree(rtas_validate_flash_data.buf);
798 remove_flash_pde(validate_pde);
799 remove_flash_pde(manage_pde);
800} 756}
801 757
802module_init(rtas_flash_init); 758module_init(rtas_flash_init);