Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 29701
b: refs/heads/master
c: dbe217a
h: refs/heads/master
i:
  29699: 5f7fb24
v: v3
  • Loading branch information
Alan Cox authored and Linus Torvalds committed Jun 25, 2006
1 parent e53756b commit 555258c
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8e3a67a99231f9f3f476bc3449e93c9a6a17f2e0
refs/heads/master: dbe217af3be08346f4b1abb885c2d9ec29c98fac
120 changes: 92 additions & 28 deletions trunk/drivers/ide/ide-cd.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
* we cannot reliably check if drive can auto-close
*/
if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
log = 0;
break;
log = 1;
break;
case UNIT_ATTENTION:
/*
Expand All @@ -417,6 +418,11 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
struct request *failed_command,
struct request_sense *sense)
{
unsigned long sector;
unsigned long bio_sectors;
unsigned long valid;
struct cdrom_info *info = drive->driver_data;

if (!cdrom_log_sense(drive, failed_command, sense))
return;

Expand All @@ -429,6 +435,37 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
if (sense->sense_key == 0x05 && sense->asc == 0x24)
return;

if (sense->error_code == 0x70) { /* Current Error */
switch(sense->sense_key) {
case MEDIUM_ERROR:
case VOLUME_OVERFLOW:
case ILLEGAL_REQUEST:
if (!sense->valid)
break;
if (failed_command == NULL ||
!blk_fs_request(failed_command))
break;
sector = (sense->information[0] << 24) |
(sense->information[1] << 16) |
(sense->information[2] << 8) |
(sense->information[3]);

bio_sectors = bio_sectors(failed_command->bio);
if (bio_sectors < 4)
bio_sectors = 4;
if (drive->queue->hardsect_size == 2048)
sector <<= 2; /* Device sector size is 2K */
sector &= ~(bio_sectors -1);
valid = (sector - failed_command->sector) << 9;

if (valid < 0)
valid = 0;
if (sector < get_capacity(info->disk) &&
drive->probed_capacity - sector < 4 * 75) {
set_capacity(info->disk, sector);
}
}
}
#if VERBOSE_IDE_CD_ERRORS
{
int i;
Expand Down Expand Up @@ -609,17 +646,23 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
sense = failed->sense;
failed->sense_len = rq->sense_len;
}

cdrom_analyze_sense_data(drive, failed, sense);
/*
* now end failed request
*/
spin_lock_irqsave(&ide_lock, flags);
end_that_request_chunk(failed, 0, failed->data_len);
end_that_request_last(failed, 0);
spin_unlock_irqrestore(&ide_lock, flags);
}

cdrom_analyze_sense_data(drive, failed, sense);
if (blk_fs_request(failed)) {
if (ide_end_dequeued_request(drive, failed, 0,
failed->hard_nr_sectors))
BUG();
} else {
spin_lock_irqsave(&ide_lock, flags);
end_that_request_chunk(failed, 0,
failed->data_len);
end_that_request_last(failed, 0);
spin_unlock_irqrestore(&ide_lock, flags);
}
} else
cdrom_analyze_sense_data(drive, NULL, sense);
}

if (!rq->current_nr_sectors && blk_fs_request(rq))
Expand All @@ -633,6 +676,13 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
ide_end_request(drive, uptodate, nsectors);
}

static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
{
if (stat & 0x80)
return;
ide_dump_status(drive, msg, stat);
}

/* Returns 0 if the request should be continued.
Returns 1 if the request was ended. */
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
Expand Down Expand Up @@ -761,16 +811,16 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
sense_key == DATA_PROTECT) {
/* No point in retrying after an illegal
request or data protect error.*/
ide_dump_status (drive, "command error", stat);
ide_dump_status_no_sense (drive, "command error", stat);
do_end_request = 1;
} else if (sense_key == MEDIUM_ERROR) {
/* No point in re-trying a zillion times on a bad
* sector... If we got here the error is not correctable */
ide_dump_status (drive, "media error (bad sector)", stat);
ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
do_end_request = 1;
} else if (sense_key == BLANK_CHECK) {
/* Disk appears blank ?? */
ide_dump_status (drive, "media error (blank)", stat);
ide_dump_status_no_sense (drive, "media error (blank)", stat);
do_end_request = 1;
} else if ((err & ~ABRT_ERR) != 0) {
/* Go to the default handler
Expand All @@ -782,13 +832,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
do_end_request = 1;
}

if (do_end_request)
cdrom_end_request(drive, 0);

/* If we got a CHECK_CONDITION status,
queue a request sense command. */
if ((stat & ERR_STAT) != 0)
cdrom_queue_request_sense(drive, NULL, NULL);
/* End a request through request sense analysis when we have
sense data. We need this in order to perform end of media
processing */

if (do_end_request) {
if (stat & ERR_STAT) {
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
spin_unlock_irqrestore(&ide_lock, flags);

cdrom_queue_request_sense(drive, rq->sense, rq);
} else
cdrom_end_request(drive, 0);
} else {
/* If we got a CHECK_CONDITION status,
queue a request sense command. */
if (stat & ERR_STAT)
cdrom_queue_request_sense(drive, NULL, NULL);
}
} else {
blk_dump_rq_flags(rq, "ide-cd: bad rq");
cdrom_end_request(drive, 0);
Expand Down Expand Up @@ -1491,8 +1555,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
}


static
int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
{
struct request_sense sense;
int retries = 10;
Expand Down Expand Up @@ -2220,6 +2283,9 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->capacity = 0x1fffff;

set_capacity(info->disk, toc->capacity * sectors_per_frame);
/* Save a private copy of te TOC capacity for error handling */
drive->probed_capacity = toc->capacity * sectors_per_frame;

blk_queue_hardsect_size(drive->queue,
sectors_per_frame << SECTOR_BITS);

Expand Down Expand Up @@ -2342,6 +2408,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (!stat && (last_written > toc->capacity)) {
toc->capacity = last_written;
set_capacity(info->disk, toc->capacity * sectors_per_frame);
drive->probed_capacity = toc->capacity * sectors_per_frame;
}

/* Remember that we've read this stuff. */
Expand Down Expand Up @@ -2698,14 +2765,11 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
* any other way to detect this...
*/
if (sense.sense_key == NOT_READY) {
if (sense.asc == 0x3a) {
if (sense.ascq == 1)
return CDS_NO_DISC;
else if (sense.ascq == 0 || sense.ascq == 2)
return CDS_TRAY_OPEN;
}
if (sense.asc == 0x3a && sense.ascq == 1)
return CDS_NO_DISC;
else
return CDS_TRAY_OPEN;
}

return CDS_DRIVE_NOT_READY;
}

Expand Down
57 changes: 57 additions & 0 deletions trunk/drivers/ide/ide-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,63 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
return ide_stopped;
}

/**
* ide_end_dequeued_request - complete an IDE I/O
* @drive: IDE device for the I/O
* @uptodate:
* @nr_sectors: number of sectors completed
*
* Complete an I/O that is no longer on the request queue. This
* typically occurs when we pull the request and issue a REQUEST_SENSE.
* We must still finish the old request but we must not tamper with the
* queue in the meantime.
*
* NOTE: This path does not handle barrier, but barrier is not supported
* on ide-cd anyway.
*/

int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
int uptodate, int nr_sectors)
{
unsigned long flags;
int ret = 1;

spin_lock_irqsave(&ide_lock, flags);

BUG_ON(!(rq->flags & REQ_STARTED));

/*
* if failfast is set on a request, override number of sectors and
* complete the whole request right now
*/
if (blk_noretry_request(rq) && end_io_error(uptodate))
nr_sectors = rq->hard_nr_sectors;

if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
rq->errors = -EIO;

/*
* decide whether to reenable DMA -- 3 is a random magic for now,
* if we DMA timeout more than 3 times, just stay in PIO
*/
if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
drive->state = 0;
HWGROUP(drive)->hwif->ide_dma_on(drive);
}

if (!end_that_request_first(rq, uptodate, nr_sectors)) {
add_disk_randomness(rq->rq_disk);
if (blk_rq_tagged(rq))
blk_queue_end_tag(drive->queue, rq);
end_that_request_last(rq, uptodate);
ret = 0;
}
spin_unlock_irqrestore(&ide_lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(ide_end_dequeued_request);


/**
* ide_complete_pm_request - end the current Power Management request
* @drive: target drive
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/ide.h
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ typedef struct ide_drive_s {
unsigned int usage; /* current "open()" count for drive */
unsigned int failures; /* current failure count */
unsigned int max_failures; /* maximum allowed failure count */
u64 probed_capacity;/* initial reported media capacity (ide-cd only currently) */

u64 capacity64; /* total number of sectors */

Expand Down Expand Up @@ -1005,6 +1006,8 @@ extern ide_hwif_t ide_hwifs[]; /* master data repository */
extern int noautodma;

extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
int uptodate, int nr_sectors);

/*
* This is used on exit from the driver to designate the next irq handler
Expand Down

0 comments on commit 555258c

Please sign in to comment.