]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/s390/char/zcore.c
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / s390 / char / zcore.c
index eefc6611412e120fd3b5ad896ca3c0a426f9d4b0..1bbae433fbd85bd20856f0882324d5da037c6d1f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * For more information please refer to Documentation/s390/zfcpdump.txt
  *
- * Copyright IBM Corp. 2003,2007
+ * Copyright IBM Corp. 2003,2008
  * Author(s): Michael Holzheu
  */
 
@@ -24,6 +24,7 @@
 #include <asm/debug.h>
 #include <asm/processor.h>
 #include <asm/irqflags.h>
+#include <asm/checksum.h>
 #include "sclp.h"
 
 #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
@@ -48,12 +49,19 @@ struct sys_info {
        union save_area lc_mask;
 };
 
+struct ipib_info {
+       unsigned long   ipib;
+       u32             checksum;
+}  __attribute__((packed));
+
 static struct sys_info sys_info;
 static struct debug_info *zcore_dbf;
 static int hsa_available;
 static struct dentry *zcore_dir;
 static struct dentry *zcore_file;
 static struct dentry *zcore_memmap_file;
+static struct dentry *zcore_reipl_file;
+static struct ipl_parameter_block *ipl_block;
 
 /*
  * Copy memory from HSA to kernel or user memory (not reentrant):
@@ -527,6 +535,33 @@ static const struct file_operations zcore_memmap_fops = {
        .release        = zcore_memmap_release,
 };
 
+static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       if (ipl_block) {
+               diag308(DIAG308_SET, ipl_block);
+               diag308(DIAG308_IPL, NULL);
+       }
+       return count;
+}
+
+static int zcore_reipl_open(struct inode *inode, struct file *filp)
+{
+       return 0;
+}
+
+static int zcore_reipl_release(struct inode *inode, struct file *filp)
+{
+       return 0;
+}
+
+static const struct file_operations zcore_reipl_fops = {
+       .owner          = THIS_MODULE,
+       .write          = zcore_reipl_write,
+       .open           = zcore_reipl_open,
+       .release        = zcore_reipl_release,
+};
+
 
 static void __init set_s390_lc_mask(union save_area *map)
 {
@@ -645,6 +680,40 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr)
        return 0;
 }
 
+/*
+ * Provide IPL parameter information block from either HSA or memory
+ * for future reipl
+ */
+static int __init zcore_reipl_init(void)
+{
+       struct ipib_info ipib_info;
+       int rc;
+
+       rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info));
+       if (rc)
+               return rc;
+       if (ipib_info.ipib == 0)
+               return 0;
+       ipl_block = (void *) __get_free_page(GFP_KERNEL);
+       if (!ipl_block)
+               return -ENOMEM;
+       if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE)
+               rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
+       else
+               rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE);
+       if (rc) {
+               free_page((unsigned long) ipl_block);
+               return rc;
+       }
+       if (csum_partial(ipl_block, ipl_block->hdr.len, 0) !=
+           ipib_info.checksum) {
+               TRACE("Checksum does not match\n");
+               free_page((unsigned long) ipl_block);
+               ipl_block = NULL;
+       }
+       return 0;
+}
+
 static int __init zcore_init(void)
 {
        unsigned char arch;
@@ -690,6 +759,10 @@ static int __init zcore_init(void)
        if (rc)
                goto fail;
 
+       rc = zcore_reipl_init();
+       if (rc)
+               goto fail;
+
        zcore_dir = debugfs_create_dir("zcore" , NULL);
        if (!zcore_dir) {
                rc = -ENOMEM;
@@ -707,9 +780,17 @@ static int __init zcore_init(void)
                rc = -ENOMEM;
                goto fail_file;
        }
+       zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir,
+                                               NULL, &zcore_reipl_fops);
+       if (!zcore_reipl_file) {
+               rc = -ENOMEM;
+               goto fail_memmap_file;
+       }
        hsa_available = 1;
        return 0;
 
+fail_memmap_file:
+       debugfs_remove(zcore_memmap_file);
 fail_file:
        debugfs_remove(zcore_file);
 fail_dir:
@@ -723,10 +804,15 @@ static void __exit zcore_exit(void)
 {
        debug_unregister(zcore_dbf);
        sclp_sdias_exit();
+       free_page((unsigned long) ipl_block);
+       debugfs_remove(zcore_reipl_file);
+       debugfs_remove(zcore_memmap_file);
+       debugfs_remove(zcore_file);
+       debugfs_remove(zcore_dir);
        diag308(DIAG308_REL_HSA, NULL);
 }
 
-MODULE_AUTHOR("Copyright IBM Corp. 2003,2007");
+MODULE_AUTHOR("Copyright IBM Corp. 2003,2008");
 MODULE_DESCRIPTION("zcore module for zfcpdump support");
 MODULE_LICENSE("GPL");