diff options
-rw-r--r-- | drivers/s390/char/zcore.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index e3b9308b0fe3..681749e7f6dd 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -62,6 +62,7 @@ static struct dentry *zcore_dir; | |||
62 | static struct dentry *zcore_file; | 62 | static struct dentry *zcore_file; |
63 | static struct dentry *zcore_memmap_file; | 63 | static struct dentry *zcore_memmap_file; |
64 | static struct dentry *zcore_reipl_file; | 64 | static struct dentry *zcore_reipl_file; |
65 | static struct dentry *zcore_hsa_file; | ||
65 | static struct ipl_parameter_block *ipl_block; | 66 | static struct ipl_parameter_block *ipl_block; |
66 | 67 | ||
67 | /* | 68 | /* |
@@ -77,6 +78,8 @@ static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode) | |||
77 | int offs, blk_num; | 78 | int offs, blk_num; |
78 | static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); | 79 | static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); |
79 | 80 | ||
81 | if (!hsa_available) | ||
82 | return -ENODATA; | ||
80 | if (count == 0) | 83 | if (count == 0) |
81 | return 0; | 84 | return 0; |
82 | 85 | ||
@@ -278,6 +281,15 @@ next: | |||
278 | } | 281 | } |
279 | 282 | ||
280 | /* | 283 | /* |
284 | * Release the HSA | ||
285 | */ | ||
286 | static void release_hsa(void) | ||
287 | { | ||
288 | diag308(DIAG308_REL_HSA, NULL); | ||
289 | hsa_available = 0; | ||
290 | } | ||
291 | |||
292 | /* | ||
281 | * Read routine for zcore character device | 293 | * Read routine for zcore character device |
282 | * First 4K are dump header | 294 | * First 4K are dump header |
283 | * Next 32MB are HSA Memory | 295 | * Next 32MB are HSA Memory |
@@ -363,8 +375,8 @@ static int zcore_open(struct inode *inode, struct file *filp) | |||
363 | 375 | ||
364 | static int zcore_release(struct inode *inode, struct file *filep) | 376 | static int zcore_release(struct inode *inode, struct file *filep) |
365 | { | 377 | { |
366 | diag308(DIAG308_REL_HSA, NULL); | 378 | if (hsa_available) |
367 | hsa_available = 0; | 379 | release_hsa(); |
368 | return 0; | 380 | return 0; |
369 | } | 381 | } |
370 | 382 | ||
@@ -474,6 +486,41 @@ static const struct file_operations zcore_reipl_fops = { | |||
474 | .llseek = no_llseek, | 486 | .llseek = no_llseek, |
475 | }; | 487 | }; |
476 | 488 | ||
489 | static ssize_t zcore_hsa_read(struct file *filp, char __user *buf, | ||
490 | size_t count, loff_t *ppos) | ||
491 | { | ||
492 | static char str[18]; | ||
493 | |||
494 | if (hsa_available) | ||
495 | snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE); | ||
496 | else | ||
497 | snprintf(str, sizeof(str), "0\n"); | ||
498 | return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); | ||
499 | } | ||
500 | |||
501 | static ssize_t zcore_hsa_write(struct file *filp, const char __user *buf, | ||
502 | size_t count, loff_t *ppos) | ||
503 | { | ||
504 | char value; | ||
505 | |||
506 | if (*ppos != 0) | ||
507 | return -EPIPE; | ||
508 | if (copy_from_user(&value, buf, 1)) | ||
509 | return -EFAULT; | ||
510 | if (value != '0') | ||
511 | return -EINVAL; | ||
512 | release_hsa(); | ||
513 | return count; | ||
514 | } | ||
515 | |||
516 | static const struct file_operations zcore_hsa_fops = { | ||
517 | .owner = THIS_MODULE, | ||
518 | .write = zcore_hsa_write, | ||
519 | .read = zcore_hsa_read, | ||
520 | .open = nonseekable_open, | ||
521 | .llseek = no_llseek, | ||
522 | }; | ||
523 | |||
477 | #ifdef CONFIG_32BIT | 524 | #ifdef CONFIG_32BIT |
478 | 525 | ||
479 | static void __init set_lc_mask(struct save_area *map) | 526 | static void __init set_lc_mask(struct save_area *map) |
@@ -658,6 +705,7 @@ static int __init zcore_init(void) | |||
658 | rc = check_sdias(); | 705 | rc = check_sdias(); |
659 | if (rc) | 706 | if (rc) |
660 | goto fail; | 707 | goto fail; |
708 | hsa_available = 1; | ||
661 | 709 | ||
662 | rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1); | 710 | rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1); |
663 | if (rc) | 711 | if (rc) |
@@ -714,9 +762,16 @@ static int __init zcore_init(void) | |||
714 | rc = -ENOMEM; | 762 | rc = -ENOMEM; |
715 | goto fail_memmap_file; | 763 | goto fail_memmap_file; |
716 | } | 764 | } |
717 | hsa_available = 1; | 765 | zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir, |
766 | NULL, &zcore_hsa_fops); | ||
767 | if (!zcore_hsa_file) { | ||
768 | rc = -ENOMEM; | ||
769 | goto fail_reipl_file; | ||
770 | } | ||
718 | return 0; | 771 | return 0; |
719 | 772 | ||
773 | fail_reipl_file: | ||
774 | debugfs_remove(zcore_reipl_file); | ||
720 | fail_memmap_file: | 775 | fail_memmap_file: |
721 | debugfs_remove(zcore_memmap_file); | 776 | debugfs_remove(zcore_memmap_file); |
722 | fail_file: | 777 | fail_file: |
@@ -733,6 +788,7 @@ static void __exit zcore_exit(void) | |||
733 | debug_unregister(zcore_dbf); | 788 | debug_unregister(zcore_dbf); |
734 | sclp_sdias_exit(); | 789 | sclp_sdias_exit(); |
735 | free_page((unsigned long) ipl_block); | 790 | free_page((unsigned long) ipl_block); |
791 | debugfs_remove(zcore_hsa_file); | ||
736 | debugfs_remove(zcore_reipl_file); | 792 | debugfs_remove(zcore_reipl_file); |
737 | debugfs_remove(zcore_memmap_file); | 793 | debugfs_remove(zcore_memmap_file); |
738 | debugfs_remove(zcore_file); | 794 | debugfs_remove(zcore_file); |