]> git.hungrycats.org Git - linux/commitdiff
[PATCH] s390: tape class for s390 tapes
authorAndrew Morton <akpm@osdl.org>
Mon, 1 Mar 2004 15:01:27 +0000 (07:01 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 1 Mar 2004 15:01:27 +0000 (07:01 -0800)
From: Martin Schwidefsky <schwidefsky@de.ibm.com>

s390 tape device driver changes:

- Add private tape class to support udev configuration.

drivers/s390/char/Makefile
drivers/s390/char/tape.h
drivers/s390/char/tape_block.c
drivers/s390/char/tape_char.c
drivers/s390/char/tape_class.c [new file with mode: 0644]
drivers/s390/char/tape_class.h [new file with mode: 0644]
drivers/s390/char/tape_core.c

index 71a158adc15cfc55fd8777a3755497b794a51428..3e48c4faddcdd1a1db31e22b2f7a72cacd8a83f6 100644 (file)
@@ -18,6 +18,6 @@ obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
 
 tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o
 tape-$(CONFIG_PROC_FS) += tape_proc.o
-tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y)
+tape-objs := tape_core.o tape_std.o tape_char.o tape_class.o $(tape-y)
 obj-$(CONFIG_S390_TAPE) += tape.o
 obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o
index c7a1274bc8ae658a103dce4d1a1deebde3fbed63..10f9eb4126389038378573e6abe33c74679834d0 100644 (file)
@@ -60,12 +60,6 @@ do { \
 #define TAPEBLOCK_HSEC_S2B     2
 #define TAPEBLOCK_RETRIES      5
 
-/* Event types for hotplug */
-#define TAPE_HOTPLUG_CHAR_ADD     1
-#define TAPE_HOTPLUG_BLOCK_ADD    2
-#define TAPE_HOTPLUG_CHAR_REMOVE  3
-#define TAPE_HOTPLUG_BLOCK_REMOVE 4
-
 enum tape_medium_state {
        MS_UNKNOWN,
        MS_LOADED,
@@ -205,6 +199,8 @@ struct tape_device {
        struct list_head                node;
 
        struct ccw_device *             cdev;
+       struct cdev *                   nt;
+       struct cdev *                   rt;
 
        /* Device discipline information. */
        struct tape_discipline *        discipline;
index c04af7213e5ba73c0efafbf272d3cfbfef831ab7..27f1226fa449cf76d599e1565bbadfc587db49a3 100644 (file)
@@ -259,9 +259,6 @@ tapeblock_setup_device(struct tape_device * device)
        INIT_WORK(&blkdat->requeue_task, tapeblock_requeue,
                tape_get_device_reference(device));
 
-       /* Will vanish */
-       tape_hotplug_event(device, tapeblock_major, TAPE_HOTPLUG_BLOCK_ADD);
-
        return 0;
 
 cleanup_queue:
@@ -274,8 +271,6 @@ cleanup_queue:
 void
 tapeblock_cleanup_device(struct tape_device *device)
 {
-       tape_hotplug_event(device, tapeblock_major, TAPE_HOTPLUG_BLOCK_REMOVE);
-
        flush_scheduled_work();
        device->blk_data.requeue_task.data = tape_put_device(device);
 
index 9994cd58effca70c3558b6c795413323d70a9021..8596025fd248f2bf3c159760f4e20f26ccede0b2 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "tape.h"
 #include "tape_std.h"
+#include "tape_class.h"
 
 #define PRINTK_HEADER "TAPE_CHAR: "
 
@@ -47,20 +48,50 @@ static struct file_operations tape_fops =
 
 static int tapechar_major = TAPECHAR_MAJOR;
 
+struct cdev *
+tapechar_register_tape_dev(struct tape_device *device, char *name, int i)
+{
+       struct cdev *   cdev;
+       char            devname[11];
+
+       sprintf(devname, "%s%i", name, i / 2);
+       cdev = register_tape_dev(
+               &device->cdev->dev,
+               MKDEV(tapechar_major, i),
+               &tape_fops,
+               devname
+       );
+
+       return ((IS_ERR(cdev)) ? NULL : cdev);
+}
+
 /*
  * This function is called for every new tapedevice
  */
 int
 tapechar_setup_device(struct tape_device * device)
 {
-       tape_hotplug_event(device, tapechar_major, TAPE_HOTPLUG_CHAR_ADD);
+       device->nt = tapechar_register_tape_dev(
+                       device,
+                       "ntibm",
+                       device->first_minor
+       );
+       device->rt = tapechar_register_tape_dev(
+                       device,
+                       "rtibm",
+                       device->first_minor + 1
+       );
+
        return 0;
 }
 
 void
 tapechar_cleanup_device(struct tape_device *device)
 {
-       tape_hotplug_event(device, tapechar_major, TAPE_HOTPLUG_CHAR_REMOVE);
+       unregister_tape_dev(device->rt);
+       device->rt = NULL;
+       unregister_tape_dev(device->nt);
+       device->nt = NULL;
 }
 
 /*
@@ -461,20 +492,17 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
 int
 tapechar_init (void)
 {
-       int rc;
+       dev_t   dev;
 
-       /* Register the tape major number to the kernel */
-       rc = register_chrdev(tapechar_major, "tape", &tape_fops);
-       if (rc < 0) {
-               PRINT_ERR("can't get major %d\n", tapechar_major);
-               DBF_EVENT(3, "TCHAR:initfail\n");
-               return rc;
-       }
-       if (tapechar_major == 0)
-               tapechar_major = rc;  /* accept dynamic major number */
-       PRINT_ERR("Tape gets major %d for char device\n", tapechar_major);
-       DBF_EVENT(3, "Tape gets major %d for char device\n", rc);
-       DBF_EVENT(3, "TCHAR:init ok\n");
+       if (alloc_chrdev_region(&dev, 0, 256, "tape") != 0)
+               return -1;
+
+       tapechar_major = MAJOR(dev);
+       PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev));
+
+#ifdef TAPE390_INTERNAL_CLASS
+       tape_setup_class();
+#endif
        return 0;
 }
 
@@ -484,5 +512,10 @@ tapechar_init (void)
 void
 tapechar_exit(void)
 {
-       unregister_chrdev (tapechar_major, "tape");
+#ifdef TAPE390_INTERNAL_CLASS
+       tape_cleanup_class();
+#endif
+       PRINT_INFO("tape releases major %d for character devices\n",
+               tapechar_major);
+       unregister_chrdev_region(MKDEV(tapechar_major, 0), 256);
 }
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
new file mode 100644 (file)
index 0000000..dd80909
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Tape class device support
+ *
+ * Author: Stefan Bader <shbader@de.ibm.com>
+ * Based on simple class device code by Greg K-H
+ */
+#include "tape_class.h"
+
+#ifndef TAPE390_INTERNAL_CLASS
+MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
+MODULE_DESCRIPTION("Tape class");
+MODULE_LICENSE("GPL");
+#endif
+
+struct class_simple *tape_class;
+
+/*
+ * Register a tape device and return a pointer to the cdev structure.
+ *
+ * device
+ *     The pointer to the struct device of the physical (base) device.
+ * drivername
+ *     The pointer to the drivers name for it's character devices.
+ * dev
+ *     The intended major/minor number. The major number may be 0 to
+ *     get a dynamic major number.
+ * fops
+ *     The pointer to the drivers file operations for the tape device.
+ * devname
+ *     The pointer to the name of the character device.
+ */
+struct cdev *register_tape_dev(
+       struct device *         device,
+       dev_t                   dev,
+       struct file_operations *fops,
+       char *                  devname
+) {
+       struct cdev *   cdev;
+       int             rc;
+       char *          s;
+
+       cdev = cdev_alloc();
+       if (!cdev)
+               return ERR_PTR(-ENOMEM);
+
+       cdev->owner = fops->owner;
+       cdev->ops   = fops;
+       cdev->dev   = dev;
+       strcpy(cdev->kobj.name, devname);
+       for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/'))
+               *s = '!';
+
+       rc = cdev_add(cdev, cdev->dev, 1);
+       if (rc) {
+               kobject_put(&cdev->kobj);
+               return ERR_PTR(rc);
+       }
+       class_simple_device_add(tape_class, cdev->dev, device, "%s", devname);
+
+       return cdev;
+}
+EXPORT_SYMBOL(register_tape_dev);
+
+void unregister_tape_dev(struct cdev *cdev)
+{
+       if (cdev != NULL) {
+               class_simple_device_remove(cdev->dev);
+               cdev_del(cdev);
+       }
+}
+EXPORT_SYMBOL(unregister_tape_dev);
+
+
+#ifndef TAPE390_INTERNAL_CLASS
+static int __init tape_init(void)
+#else
+int tape_setup_class(void)
+#endif
+{
+       tape_class = class_simple_create(THIS_MODULE, "tape390");
+       return 0;
+}
+
+#ifndef TAPE390_INTERNAL_CLASS
+static void __exit tape_exit(void)
+#else
+void tape_cleanup_class(void)
+#endif
+{
+       class_simple_destroy(tape_class);
+       tape_class = NULL;
+}
+
+#ifndef TAPE390_INTERNAL_CLASS
+postcore_initcall(tape_init);
+module_exit(tape_exit);
+#else
+EXPORT_SYMBOL(tape_setup_class);
+EXPORT_SYMBOL(tape_cleanup_class);
+#endif
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
new file mode 100644 (file)
index 0000000..04fbb7d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Tape class device support
+ *
+ * Author: Stefan Bader <shbader@de.ibm.com>
+ * Based on simple class device code by Greg K-H
+ */
+#ifndef __TAPE_CLASS_H__
+#define __TAPE_CLASS_H__
+
+#if 0
+#include <linux/init.h>
+#include <linux/module.h>
+#endif
+
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/kobject.h>
+#include <linux/kobj_map.h>
+#include <linux/cdev.h>
+
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+
+#define TAPE390_INTERNAL_CLASS
+
+/*
+ * Register a tape device and return a pointer to the cdev structure.
+ *
+ * device
+ *     The pointer to the struct device of the physical (base) device.
+ * drivername
+ *     The pointer to the drivers name for it's character devices.
+ * dev
+ *     The intended major/minor number. The major number may be 0 to
+ *     get a dynamic major number.
+ * fops
+ *     The pointer to the drivers file operations for the tape device.
+ * devname
+ *     The pointer to the name of the character device.
+ */
+struct cdev *register_tape_dev(
+       struct device *         device,
+       dev_t                   dev,
+       struct file_operations *fops,
+       char *                  devname
+);
+void unregister_tape_dev(struct cdev *cdev);
+
+#ifdef TAPE390_INTERNAL_CLASS
+int tape_setup_class(void);
+void tape_cleanup_class(void);
+#endif
+
+#endif /* __TAPE_CLASS_H__ */
index 137653d4df6b925c32ac241dec5d7a439a6d8564..412cf5a8ed60c8d3e7e770f38483581efab47893 100644 (file)
@@ -237,10 +237,7 @@ __tape_halt_io(struct tape_device *device, struct tape_request *request)
 
        rc = 0;
        for (retries = 0; retries < 5; retries++) {
-               if (retries < 2)
-                       rc = ccw_device_halt(device->cdev, (long) request);
-               else
-                       rc = ccw_device_clear(device->cdev, (long) request);
+               rc = ccw_device_clear(device->cdev, (long) request);
 
                if (rc == 0) {                     /* Termination successful */
                        request->rc     = -EIO;
@@ -1015,63 +1012,6 @@ tape_mtop(struct tape_device *device, int mt_op, int mt_count)
 
 }
 
-/*
- * Hutplug event support.
- */
-void
-tape_hotplug_event(struct tape_device *device, int devmaj, int action) {
-#ifdef CONFIG_HOTPLUG
-       char *argv[3];
-       char *envp[8];
-       char  busid[20];
-       char  major[20];
-       char  minor[20];
-
-       /* Call the busid DEVNO to be compatible with old tape.agent. */
-       sprintf(busid, "DEVNO=%s",   device->cdev->dev.bus_id);
-       sprintf(major, "MAJOR=%d",   devmaj);
-       sprintf(minor, "MINOR=%d",   device->first_minor);
-
-       argv[0] = hotplug_path;
-       argv[1] = "tape";
-       argv[2] = NULL;
-
-       envp[0] = "HOME=/";
-       envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
-       switch (action) {
-               case TAPE_HOTPLUG_CHAR_ADD:
-               case TAPE_HOTPLUG_BLOCK_ADD:
-                       envp[2] = "ACTION=add";
-                       break;
-               case TAPE_HOTPLUG_CHAR_REMOVE:
-               case TAPE_HOTPLUG_BLOCK_REMOVE:
-                       envp[2] = "ACTION=remove";
-                       break;
-               default:
-                       BUG();
-       }
-       switch (action) {
-               case TAPE_HOTPLUG_CHAR_ADD:
-               case TAPE_HOTPLUG_CHAR_REMOVE:
-                       envp[3] = "INTERFACE=char";
-                       break;
-               case TAPE_HOTPLUG_BLOCK_ADD:
-               case TAPE_HOTPLUG_BLOCK_REMOVE:
-                       envp[3] = "INTERFACE=block";
-                       break;
-               default:
-                       BUG();
-       }
-       envp[4] = busid;
-       envp[5] = major;
-       envp[6] = minor;
-       envp[7] = NULL;
-
-       call_usermodehelper(argv[0], argv, envp, 0);
-#endif
-}
-
 /*
  * Tape init function.
  */
@@ -1083,7 +1023,7 @@ tape_init (void)
 #ifdef DBF_LIKE_HELL
        debug_set_level(tape_dbf_area, 6);
 #endif
-       DBF_EVENT(3, "tape init: ($Revision: 1.41 $)\n");
+       DBF_EVENT(3, "tape init: ($Revision: 1.44 $)\n");
        tape_proc_init();
        tapechar_init ();
        tapeblock_init ();
@@ -1108,7 +1048,7 @@ tape_exit(void)
 MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
              "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
 MODULE_DESCRIPTION("Linux on zSeries channel attached "
-                  "tape device driver ($Revision: 1.41 $)");
+                  "tape device driver ($Revision: 1.44 $)");
 MODULE_LICENSE("GPL");
 
 module_init(tape_init);