aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/rtas_flash.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-04-12 19:48:49 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-05-01 17:29:45 -0400
commite8eeded3c5226fe420f9c6733cf5ada2faa3087a (patch)
treeeb7f78e3f1f2778451399760bdd77c9f79fbe89c /arch/powerpc/kernel/rtas_flash.c
parent819695abb762a625d2ef8f2a6fbf6debeec35b61 (diff)
ppc: Clean up rtas_flash driver somewhat
Clean up some of the problems with the rtas_flash driver: (1) It shouldn't fiddle with the internals of the procfs filesystem (altering pde->count). (2) If pid namespaces are in effect, then you can get multiple inodes connected to a single pde, thereby rendering the pde->count > 2 test useless. (3) The pde->count fudging doesn't work for forked, dup'd or cloned file descriptors, so add static mutexes and use them to wrap access to the driver through read, write and release methods. (4) The driver can only handle one device, so allocate most of the data previously attached to the pde->data as static variables instead (though allocate the validation data buffer with kmalloc). (5) We don't need to save the pde pointers as long as we have the filenames available for removal. (6) Don't try to multiplex what the update file read method does based on the filename. Instead provide separate file ops and split the function. Whilst we're at it, tabulate the procfile information and loop through it when creating or destroying them rather than manually coding each one. [Folded fixes from Vasant Hegde <hegdevasant@linux.vnet.ibm.com>] Signed-off-by: David Howells <dhowells@redhat.com> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> cc: Paul Mackerras <paulus@samba.org> cc: Anton Blanchard <anton@samba.org> cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/powerpc/kernel/rtas_flash.c')
-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);