diff options
-rw-r--r-- | drivers/ide/ide-cd.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index a4afd9082c4a..7bbdeb7e3bc4 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -265,7 +265,43 @@ static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) | |||
265 | cdrom_analyze_sense_data(drive, NULL, sense); | 265 | cdrom_analyze_sense_data(drive, NULL, sense); |
266 | } | 266 | } |
267 | 267 | ||
268 | |||
268 | /* | 269 | /* |
270 | * Allow the drive 5 seconds to recover; some devices will return NOT_READY | ||
271 | * while flushing data from cache. | ||
272 | * | ||
273 | * returns: 0 failed (write timeout expired) | ||
274 | * 1 success | ||
275 | */ | ||
276 | static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) | ||
277 | { | ||
278 | |||
279 | struct cdrom_info *info = drive->driver_data; | ||
280 | |||
281 | if (!rq->errors) | ||
282 | info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY; | ||
283 | |||
284 | rq->errors = 1; | ||
285 | |||
286 | if (time_after(jiffies, info->write_timeout)) | ||
287 | return 0; | ||
288 | else { | ||
289 | struct request_queue *q = drive->queue; | ||
290 | unsigned long flags; | ||
291 | |||
292 | /* | ||
293 | * take a breather relying on the unplug timer to kick us again | ||
294 | */ | ||
295 | |||
296 | spin_lock_irqsave(q->queue_lock, flags); | ||
297 | blk_plug_device(q); | ||
298 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
299 | |||
300 | return 1; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | /** | ||
269 | * Returns: | 305 | * Returns: |
270 | * 0: if the request should be continued. | 306 | * 0: if the request should be continued. |
271 | * 1: if the request will be going through error recovery. | 307 | * 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) | |||
348 | /* fail the request */ | 384 | /* fail the request */ |
349 | printk(KERN_ERR PFX "%s: tray open\n", | 385 | printk(KERN_ERR PFX "%s: tray open\n", |
350 | drive->name); | 386 | drive->name); |
351 | do_end_request = 1; | ||
352 | } else { | 387 | } else { |
353 | struct cdrom_info *info = drive->driver_data; | 388 | if (ide_cd_breathe(drive, rq)) |
354 | |||
355 | /* | ||
356 | * Allow the drive 5 seconds to recover, some | ||
357 | * devices will return this error while flushing | ||
358 | * data from cache. | ||
359 | */ | ||
360 | if (!rq->errors) | ||
361 | info->write_timeout = jiffies + | ||
362 | ATAPI_WAIT_WRITE_BUSY; | ||
363 | rq->errors = 1; | ||
364 | if (time_after(jiffies, info->write_timeout)) | ||
365 | do_end_request = 1; | ||
366 | else { | ||
367 | struct request_queue *q = drive->queue; | ||
368 | unsigned long flags; | ||
369 | |||
370 | /* | ||
371 | * take a breather relying on the unplug | ||
372 | * timer to kick us again | ||
373 | */ | ||
374 | spin_lock_irqsave(q->queue_lock, flags); | ||
375 | blk_plug_device(q); | ||
376 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
377 | |||
378 | return 1; | 389 | return 1; |
379 | } | ||
380 | } | 390 | } |
391 | do_end_request = 1; | ||
381 | } else if (sense_key == UNIT_ATTENTION) { | 392 | } else if (sense_key == UNIT_ATTENTION) { |
382 | /* media change */ | 393 | /* media change */ |
383 | cdrom_saw_media_change(drive); | 394 | cdrom_saw_media_change(drive); |