extern int tape_do_io(struct tape_device *, struct tape_request *);
 extern int tape_do_io_async(struct tape_device *, struct tape_request *);
 extern int tape_do_io_interruptible(struct tape_device *, struct tape_request *);
+extern int tape_cancel_io(struct tape_device *, struct tape_request *);
 void tape_hotplug_event(struct tape_device *, int major, int action);
 
 static inline int
 
                 */
                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
        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
  */
         * error might still apply. So we just schedule the request to be
         * started later.
         */
-       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);
+       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_work(&device->tape_dnr);
+               schedule_delayed_work(&device->tape_dnr, HZ);
                return;
        }
 
 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);
 
 {
        struct tape_request *   request;
        struct tape_device *    device;
+       int rc;
 
        request = (struct tape_request *) data;
        if ((device = request->device) == NULL)
                BUG();
 
-       spin_lock_irq(get_ccwdev_lock(device->cdev));
-       if (request->callback != NULL) {
-               DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
+       DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
                        device->cdev_id);
-               PRINT_ERR("%s: Assignment timeout. Device busy.\n",
-                       device->cdev->dev.bus_id);
-               ccw_device_clear(device->cdev, (long) request);
-       }
-       spin_unlock_irq(get_ccwdev_lock(device->cdev));
+       rc = tape_cancel_io(device, request);
+       if(rc)
+               PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n",
+                       device->cdev->dev.bus_id, rc);
+
 }
 
 int