linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / s390 / char / tape_core.c
index 2826aed..4ea438c 100644 (file)
@@ -11,6 +11,7 @@
  *              Stefan Bader <shbader@de.ibm.com>
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>             // for kernel parameters
 #include <linux/kmod.h>             // for requesting modules
@@ -209,14 +210,18 @@ tape_state_set(struct tape_device *device, enum tape_state newstate)
                return;
        }
        DBF_EVENT(4, "ts. dev:  %x\n", device->first_minor);
-       DBF_EVENT(4, "old ts:\t\n");
-       if (device->tape_state < TS_SIZE && device->tape_state >=0 )
+       if (device->tape_state < TO_SIZE && device->tape_state >= 0)
+               str = tape_state_verbose[device->tape_state];
+       else
+               str = "UNKNOWN TS";
+       DBF_EVENT(4, "old ts:   %s\n", str);
+       if (device->tape_state < TO_SIZE && device->tape_state >=0 )
                str = tape_state_verbose[device->tape_state];
        else
                str = "UNKNOWN TS";
        DBF_EVENT(4, "%s\n", str);
        DBF_EVENT(4, "new ts:\t\n");
-       if (newstate < TS_SIZE && newstate >= 0)
+       if (newstate < TO_SIZE && newstate >= 0)
                str = tape_state_verbose[newstate];
        else
                str = "UNKNOWN TS";
@@ -448,14 +453,16 @@ tape_alloc_device(void)
 {
        struct tape_device *device;
 
-       device = kzalloc(sizeof(struct tape_device), GFP_KERNEL);
+       device = (struct tape_device *)
+               kmalloc(sizeof(struct tape_device), GFP_KERNEL);
        if (device == NULL) {
                DBF_EXCEPTION(2, "ti:no mem\n");
                PRINT_INFO ("can't allocate memory for "
                            "tape info structure\n");
                return ERR_PTR(-ENOMEM);
        }
-       device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA);
+       memset(device, 0, sizeof(struct tape_device));
+       device->modeset_byte = (char *) kmalloc(1, GFP_KERNEL | GFP_DMA);
        if (device->modeset_byte == NULL) {
                DBF_EXCEPTION(2, "ti:no mem\n");
                PRINT_INFO("can't allocate memory for modeset byte\n");
@@ -543,24 +550,20 @@ int
 tape_generic_probe(struct ccw_device *cdev)
 {
        struct tape_device *device;
-       int ret;
 
        device = tape_alloc_device();
        if (IS_ERR(device))
                return -ENODEV;
-       ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
-       ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
-       if (ret) {
-               tape_put_device(device);
-               PRINT_ERR("probe failed for tape device %s\n", cdev->dev.bus_id);
-               return ret;
-       }
+       PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
        cdev->dev.driver_data = device;
-       cdev->handler = __tape_do_irq;
        device->cdev = cdev;
        device->cdev_id = busid_to_int(cdev->dev.bus_id);
-       PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
-       return ret;
+       cdev->handler = __tape_do_irq;
+
+       ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
+       sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
+
+       return 0;
 }
 
 static inline void
@@ -656,30 +659,34 @@ tape_alloc_request(int cplength, int datasize)
 
        DBF_LH(6, "tape_alloc_request(%d, %d)\n", cplength, datasize);
 
-       request = kzalloc(sizeof(struct tape_request), GFP_KERNEL);
+       request = (struct tape_request *) kmalloc(sizeof(struct tape_request),
+                                                 GFP_KERNEL);
        if (request == NULL) {
                DBF_EXCEPTION(1, "cqra nomem\n");
                return ERR_PTR(-ENOMEM);
        }
+       memset(request, 0, sizeof(struct tape_request));
        /* allocate channel program */
        if (cplength > 0) {
-               request->cpaddr = kcalloc(cplength, sizeof(struct ccw1),
+               request->cpaddr = kmalloc(cplength*sizeof(struct ccw1),
                                          GFP_ATOMIC | GFP_DMA);
                if (request->cpaddr == NULL) {
                        DBF_EXCEPTION(1, "cqra nomem\n");
                        kfree(request);
                        return ERR_PTR(-ENOMEM);
                }
+               memset(request->cpaddr, 0, cplength*sizeof(struct ccw1));
        }
        /* alloc small kernel buffer */
        if (datasize > 0) {
-               request->cpdata = kzalloc(datasize, GFP_KERNEL | GFP_DMA);
+               request->cpdata = kmalloc(datasize, GFP_KERNEL | GFP_DMA);
                if (request->cpdata == NULL) {
                        DBF_EXCEPTION(1, "cqra nomem\n");
                        kfree(request->cpaddr);
                        kfree(request);
                        return ERR_PTR(-ENOMEM);
                }
+               memset(request->cpdata, 0, datasize);
        }
        DBF_LH(6, "New request %p(%p/%p)\n", request, request->cpaddr,
                request->cpdata);
@@ -754,13 +761,6 @@ __tape_start_next_request(struct tape_device *device)
                 */
                if (request->status == TAPE_REQUEST_IN_IO)
                        return;
-               /*
-                * Request has already been stopped. We have to wait until
-                * the request is removed from the queue in the interrupt
-                * handling.
-                */
-               if (request->status == TAPE_REQUEST_DONE)
-                       return;
 
                /*
                 * We wanted to cancel the request but the common I/O layer
@@ -1015,7 +1015,7 @@ tape_do_io_interruptible(struct tape_device *device,
                                wq,
                                (request->callback == NULL)
                        );
-               } while (rc == -ERESTARTSYS);
+               } while (rc != -ERESTARTSYS);
 
                DBF_EVENT(3, "IO stopped on %08x\n", device->cdev_id);
                rc = -ERESTARTSYS;
@@ -1023,20 +1023,6 @@ tape_do_io_interruptible(struct tape_device *device,
        return rc;
 }
 
-/*
- * Stop running ccw.
- */
-int
-tape_cancel_io(struct tape_device *device, struct tape_request *request)
-{
-       int rc;
-
-       spin_lock_irq(get_ccwdev_lock(device->cdev));
-       rc = __tape_cancel_io(device, request);
-       spin_unlock_irq(get_ccwdev_lock(device->cdev));
-       return rc;
-}
-
 /*
  * Tape interrupt routine, called from the ccw_device layer
  */
@@ -1078,16 +1064,15 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        /*
         * If the condition code is not zero and the start function bit is
         * still set, this is an deferred error and the last start I/O did
-        * not succeed. At this point the condition that caused the deferred
-        * error might still apply. So we just schedule the request to be
-        * started later.
+        * not succeed. Restart the request now.
         */
-       if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC) &&
-           (request->status == TAPE_REQUEST_IN_IO)) {
-               DBF_EVENT(3,"(%08x): deferred cc=%i, fctl=%i. restarting\n",
-                       device->cdev_id, irb->scsw.cc, irb->scsw.fctl);
-               request->status = TAPE_REQUEST_QUEUED;
-               schedule_delayed_work(&device->tape_dnr, HZ);
+       if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
+               PRINT_WARN("(%s): deferred cc=%i. restaring\n",
+                       cdev->dev.bus_id,
+                       irb->scsw.cc);
+               rc = __tape_start_io(device, request);
+               if (rc)
+                       __tape_end_request(device, request, rc);
                return;
        }
 
@@ -1301,5 +1286,4 @@ EXPORT_SYMBOL(tape_dump_sense_dbf);
 EXPORT_SYMBOL(tape_do_io);
 EXPORT_SYMBOL(tape_do_io_async);
 EXPORT_SYMBOL(tape_do_io_interruptible);
-EXPORT_SYMBOL(tape_cancel_io);
 EXPORT_SYMBOL(tape_mtop);