linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / s390 / block / xpram.c
index ca7d51f..54ecd54 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/hdreg.h>  /* HDIO_GETGEO */
 #include <linux/sysdev.h>
 #include <linux/bio.h>
+#include <linux/devfs_fs_kernel.h>
 #include <asm/uaccess.h>
 
 #define XPRAM_NAME     "xpram"
 #define PRINT_ERR(x...)                printk(KERN_ERR XPRAM_NAME " error:" x)
 
 
+static struct sysdev_class xpram_sysclass = {
+       set_kset_name("xpram"),
+};
+
+static struct sys_device xpram_sys_device = {
+       .id     = 0,
+       .cls    = &xpram_sysclass,
+}; 
+
 typedef struct {
        unsigned int    size;           /* size of xpram segment in pages */
        unsigned int    offset;         /* start page of xpram segment */
@@ -62,11 +72,11 @@ static int xpram_devs;
 /*
  * Parameter parsing functions.
  */
-static int __initdata devs = XPRAM_DEVS;
-static char __initdata *sizes[XPRAM_MAX_DEVS];
+static int devs = XPRAM_DEVS;
+static unsigned int sizes[XPRAM_MAX_DEVS];
 
 module_param(devs, int, 0);
-module_param_array(sizes, charp, NULL, 0);
+module_param_array(sizes, int, NULL, 0);
 
 MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \
                 "the default is " __MODULE_STRING(XPRAM_DEVS) "\n");
@@ -77,6 +87,59 @@ MODULE_PARM_DESC(sizes, "list of device (partition) sizes " \
                 "claimed by explicit sizes\n");
 MODULE_LICENSE("GPL");
 
+#ifndef MODULE
+/*
+ * Parses the kernel parameters given in the kernel parameter line.
+ * The expected format is
+ *           <number_of_partitions>[","<partition_size>]*
+ * where
+ *           devices is a positive integer that initializes xpram_devs
+ *           each size is a non-negative integer possibly followed by a
+ *           magnitude (k,K,m,M,g,G), the list of sizes initialises
+ *           xpram_sizes
+ *
+ * Arguments
+ *           str: substring of kernel parameter line that contains xprams
+ *                kernel parameters.
+ *
+ * Result    0 on success, -EINVAL else -- only for Version > 2.3
+ *
+ * Side effects
+ *           the global variabls devs is set to the value of
+ *           <number_of_partitions> and sizes[i] is set to the i-th
+ *           partition size (if provided). A parsing error of a value
+ *           results in this value being set to -EINVAL.
+ */
+static int __init xpram_setup (char *str)
+{
+       char *cp;
+       int i;
+
+       devs = simple_strtoul(str, &cp, 10);
+       if (cp <= str || devs > XPRAM_MAX_DEVS)
+               return 0;
+       for (i = 0; (i < devs) && (*cp++ == ','); i++) {
+               sizes[i] = simple_strtoul(cp, &cp, 10);
+               if (*cp == 'g' || *cp == 'G') {
+                       sizes[i] <<= 20;
+                       cp++;
+               } else if (*cp == 'm' || *cp == 'M') {
+                       sizes[i] <<= 10;
+                       cp++;
+               } else if (*cp == 'k' || *cp == 'K')
+                       cp++;
+               while (isspace(*cp)) cp++;
+       }
+       if (*cp == ',' && i >= devs)
+               PRINT_WARN("partition sizes list has too many entries.\n");
+       else if (*cp != 0)
+               PRINT_WARN("ignored '%s' at end of parameter string.\n", cp);
+       return 1;
+}
+
+__setup("xpram_parts=", xpram_setup);
+#endif
+
 /*
  * Copy expanded memory page (4kB) into main memory                  
  * Arguments                                                         
@@ -295,7 +358,6 @@ static int __init xpram_setup_sizes(unsigned long pages)
 {
        unsigned long mem_needed;
        unsigned long mem_auto;
-       unsigned long long size;
        int mem_auto_no;
        int i;
 
@@ -313,19 +375,7 @@ static int __init xpram_setup_sizes(unsigned long pages)
        mem_needed = 0;
        mem_auto_no = 0;
        for (i = 0; i < xpram_devs; i++) {
-               if (sizes[i]) {
-                       size = simple_strtoull(sizes[i], &sizes[i], 0);
-                       switch (sizes[i][0]) {
-                       case 'g':
-                       case 'G':
-                               size <<= 20;
-                               break;
-                       case 'm':
-                       case 'M':
-                               size <<= 10;
-                       }
-                       xpram_sizes[i] = (size + 3) & -4UL;
-               }
+               xpram_sizes[i] = (sizes[i] + 3) & -4UL;
                if (xpram_sizes[i])
                        mem_needed += xpram_sizes[i];
                else
@@ -389,6 +439,8 @@ static int __init xpram_setup_blkdev(void)
        if (rc < 0)
                goto out;
 
+       devfs_mk_dir("slram");
+
        /*
         * Assign the other needed values: make request function, sizes and
         * hardsect size. All the minor devices feature the same value.
@@ -417,12 +469,14 @@ static int __init xpram_setup_blkdev(void)
                disk->private_data = &xpram_devices[i];
                disk->queue = xpram_queue;
                sprintf(disk->disk_name, "slram%d", i);
+               sprintf(disk->devfs_name, "slram/%d", i);
                set_capacity(disk, xpram_sizes[i] << 1);
                add_disk(disk);
        }
 
        return 0;
 out_unreg:
+       devfs_remove("slram");
        unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
 out:
        while (i--)
@@ -441,7 +495,10 @@ static void __exit xpram_exit(void)
                put_disk(xpram_disks[i]);
        }
        unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
+       devfs_remove("slram");
        blk_cleanup_queue(xpram_queue);
+       sysdev_unregister(&xpram_sys_device);
+       sysdev_class_unregister(&xpram_sysclass);
 }
 
 static int __init xpram_init(void)
@@ -459,7 +516,19 @@ static int __init xpram_init(void)
        rc = xpram_setup_sizes(xpram_pages);
        if (rc)
                return rc;
-       return xpram_setup_blkdev();
+       rc = sysdev_class_register(&xpram_sysclass);
+       if (rc)
+               return rc;
+
+       rc = sysdev_register(&xpram_sys_device);
+       if (rc) {
+               sysdev_class_unregister(&xpram_sysclass);
+               return rc;
+       }
+       rc = xpram_setup_blkdev();
+       if (rc)
+               sysdev_unregister(&xpram_sys_device);
+       return rc;
 }
 
 module_init(xpram_init);