patch-pre2.0.12 linux/drivers/scsi/sd.c
Next file: linux/drivers/scsi/sr.c
Previous file: linux/drivers/scsi/scsi_ioctl.c
Back to the patch index
Back to the overall index
- Lines: 103
- Date:
Tue Jun 4 12:56:48 1996
- Orig file:
pre2.0.11/linux/drivers/scsi/sd.c
- Orig date:
Mon Jun 3 16:46:56 1996
diff -u --recursive --new-file pre2.0.11/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
@@ -218,11 +218,45 @@
{
int result = SCpnt->result;
int this_count = SCpnt->bufflen >> 9;
+ int good_sectors = (result == 0 ? this_count : 0);
+ int block_sectors = 1;
#ifdef DEBUG
printk("sd%c : rw_intr(%d, %d)\n", 'a' + MINOR(SCpnt->request.rq_dev),
SCpnt->host->host_no, result);
#endif
+
+ /*
+ Handle MEDIUM ERRORs that indicate partial success. Since this is a
+ relatively rare error condition, no care is taken to avoid unnecessary
+ additional work such as memcpy's that could be avoided.
+ */
+
+ if (driver_byte(result) != 0 && /* An error occurred */
+ SCpnt->sense_buffer[0] == 0xF0 && /* Sense data is valid */
+ SCpnt->sense_buffer[2] == MEDIUM_ERROR)
+ {
+ long error_sector = (SCpnt->sense_buffer[3] << 24) |
+ (SCpnt->sense_buffer[4] << 16) |
+ (SCpnt->sense_buffer[5] << 8) |
+ SCpnt->sense_buffer[6];
+ int sector_size =
+ rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].sector_size;
+ if (SCpnt->request.bh != NULL)
+ block_sectors = SCpnt->request.bh->b_size >> 9;
+ if (sector_size == 1024)
+ {
+ error_sector <<= 1;
+ if (block_sectors < 2) block_sectors = 2;
+ }
+ else if (sector_size == 256)
+ error_sector >>= 1;
+ error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
+ error_sector &= ~ (block_sectors - 1);
+ good_sectors = error_sector - SCpnt->request.sector;
+ if (good_sectors < 0 || good_sectors >= this_count)
+ good_sectors = 0;
+ }
/*
* First case : we assume that the command succeeded. One of two things
@@ -230,7 +264,7 @@
* sectors that we were unable to read last time.
*/
- if (!result) {
+ if (good_sectors > 0) {
#ifdef DEBUG
printk("sd%c : %d sectors remain.\n", 'a' + MINOR(SCpnt->request.rq_dev),
@@ -291,11 +325,16 @@
SCpnt->request.sector, this_count);
}
}
- SCpnt = end_scsi_request(SCpnt, 1, this_count);
- requeue_sd_request(SCpnt);
- return;
+ SCpnt = end_scsi_request(SCpnt, 1, good_sectors);
+ if (result == 0)
+ {
+ requeue_sd_request(SCpnt);
+ return;
+ }
}
+ if (good_sectors == 0) {
+
/* Free up any indirection buffers we allocated for DMA purposes. */
if (SCpnt->use_sg) {
struct scatterlist * sgpnt;
@@ -319,7 +358,8 @@
if (SCpnt->buffer != SCpnt->request.buffer)
scsi_free(SCpnt->buffer, SCpnt->bufflen);
}
-
+ }
+
/*
* Now, if we were good little boys and girls, Santa left us a request
* sense buffer. We can extract information from this, so we
@@ -382,6 +422,17 @@
/* ???? */
}
}
+
+ if (SCpnt->sense_buffer[2] == MEDIUM_ERROR) {
+ printk("scsi%d: MEDIUM ERROR on channel %d, id %d, lun %d, CDB: ",
+ SCpnt->host->host_no, (int) SCpnt->channel,
+ (int) SCpnt->target, (int) SCpnt->lun);
+ print_command(SCpnt->cmnd);
+ print_sense("sr", SCpnt);
+ SCpnt = end_scsi_request(SCpnt, 0, block_sectors);
+ requeue_sd_request(SCpnt);
+ return;
+ }
} /* driver byte != 0 */
if (result) {
printk("SCSI disk error : host %d channel %d id %d lun %d return code = %x\n",
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this