|
@@ -265,7 +265,43 @@ static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
|
|
|
cdrom_analyze_sense_data(drive, NULL, sense);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/*
|
|
|
+ * Allow the drive 5 seconds to recover; some devices will return NOT_READY
|
|
|
+ * while flushing data from cache.
|
|
|
+ *
|
|
|
+ * returns: 0 failed (write timeout expired)
|
|
|
+ * 1 success
|
|
|
+ */
|
|
|
+static int ide_cd_breathe(ide_drive_t *drive, struct request *rq)
|
|
|
+{
|
|
|
+
|
|
|
+ struct cdrom_info *info = drive->driver_data;
|
|
|
+
|
|
|
+ if (!rq->errors)
|
|
|
+ info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
|
|
|
+
|
|
|
+ rq->errors = 1;
|
|
|
+
|
|
|
+ if (time_after(jiffies, info->write_timeout))
|
|
|
+ return 0;
|
|
|
+ else {
|
|
|
+ struct request_queue *q = drive->queue;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * take a breather relying on the unplug timer to kick us again
|
|
|
+ */
|
|
|
+
|
|
|
+ spin_lock_irqsave(q->queue_lock, flags);
|
|
|
+ blk_plug_device(q);
|
|
|
+ spin_unlock_irqrestore(q->queue_lock, flags);
|
|
|
+
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
* Returns:
|
|
|
* 0: if the request should be continued.
|
|
|
* 1: if the request will be going through error recovery.
|
|
@@ -348,36 +384,11 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
|
|
|
/* fail the request */
|
|
|
printk(KERN_ERR PFX "%s: tray open\n",
|
|
|
drive->name);
|
|
|
- do_end_request = 1;
|
|
|
} else {
|
|
|
- struct cdrom_info *info = drive->driver_data;
|
|
|
-
|
|
|
- /*
|
|
|
- * Allow the drive 5 seconds to recover, some
|
|
|
- * devices will return this error while flushing
|
|
|
- * data from cache.
|
|
|
- */
|
|
|
- if (!rq->errors)
|
|
|
- info->write_timeout = jiffies +
|
|
|
- ATAPI_WAIT_WRITE_BUSY;
|
|
|
- rq->errors = 1;
|
|
|
- if (time_after(jiffies, info->write_timeout))
|
|
|
- do_end_request = 1;
|
|
|
- else {
|
|
|
- struct request_queue *q = drive->queue;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- /*
|
|
|
- * take a breather relying on the unplug
|
|
|
- * timer to kick us again
|
|
|
- */
|
|
|
- spin_lock_irqsave(q->queue_lock, flags);
|
|
|
- blk_plug_device(q);
|
|
|
- spin_unlock_irqrestore(q->queue_lock, flags);
|
|
|
-
|
|
|
+ if (ide_cd_breathe(drive, rq))
|
|
|
return 1;
|
|
|
- }
|
|
|
}
|
|
|
+ do_end_request = 1;
|
|
|
} else if (sense_key == UNIT_ATTENTION) {
|
|
|
/* media change */
|
|
|
cdrom_saw_media_change(drive);
|