|
@@ -761,6 +761,13 @@ __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
|
|
@@ -1023,6 +1030,20 @@ 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
|
|
|
*/
|
|
@@ -1068,12 +1089,12 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
|
|
* 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;
|
|
|
}
|
|
|
|
|
@@ -1287,4 +1308,5 @@ 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);
|