aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c116
1 files changed, 75 insertions, 41 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b061ba2c31d8..3131adcc1f87 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -270,13 +270,28 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
ata_scsi_park_show, ata_scsi_park_store);
EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
-static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
+ if (!cmd)
+ return;
+
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
}
+void ata_scsi_set_sense_information(struct scsi_cmnd *cmd,
+ const struct ata_taskfile *tf)
+{
+ u64 information;
+
+ if (!cmd)
+ return;
+
+ information = ata_tf_read_block(tf, NULL);
+ scsi_set_sense_information(cmd->sense_buffer, information);
+}
+
static ssize_t
ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -799,26 +814,27 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
if (stat & ATA_BUSY) {
printk("Busy }\n"); /* Data is not valid in this case */
} else {
- if (stat & 0x40) printk("DriveReady ");
- if (stat & 0x20) printk("DeviceFault ");
- if (stat & 0x10) printk("SeekComplete ");
- if (stat & 0x08) printk("DataRequest ");
- if (stat & 0x04) printk("CorrectedError ");
- if (stat & 0x02) printk("Index ");
- if (stat & 0x01) printk("Error ");
+ if (stat & ATA_DRDY) printk("DriveReady ");
+ if (stat & ATA_DF) printk("DeviceFault ");
+ if (stat & ATA_DSC) printk("SeekComplete ");
+ if (stat & ATA_DRQ) printk("DataRequest ");
+ if (stat & ATA_CORR) printk("CorrectedError ");
+ if (stat & ATA_SENSE) printk("Sense ");
+ if (stat & ATA_ERR) printk("Error ");
printk("}\n");
if (err) {
printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
- if (err & 0x04) printk("DriveStatusError ");
- if (err & 0x80) {
- if (err & 0x04) printk("BadCRC ");
+ if (err & ATA_ABORTED) printk("DriveStatusError ");
+ if (err & ATA_ICRC) {
+ if (err & ATA_ABORTED)
+ printk("BadCRC ");
else printk("Sector ");
}
- if (err & 0x40) printk("UncorrectableError ");
- if (err & 0x10) printk("SectorIdNotFound ");
- if (err & 0x02) printk("TrackZeroNotFound ");
- if (err & 0x01) printk("AddrMarkNotFound ");
+ if (err & ATA_UNC) printk("UncorrectableError ");
+ if (err & ATA_IDNF) printk("SectorIdNotFound ");
+ if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
+ if (err & ATA_AMNF) printk("AddrMarkNotFound ");
printk("}\n");
}
}
@@ -849,40 +865,59 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
/* Based on the 3ware driver translation table */
static const unsigned char sense_table[][4] = {
/* BBD|ECC|ID|MAR */
- {0xd1, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command
+ {0xd1, ABORTED_COMMAND, 0x00, 0x00},
+ // Device busy Aborted command
/* BBD|ECC|ID */
- {0xd0, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command
+ {0xd0, ABORTED_COMMAND, 0x00, 0x00},
+ // Device busy Aborted command
/* ECC|MC|MARK */
- {0x61, HARDWARE_ERROR, 0x00, 0x00}, // Device fault Hardware error
+ {0x61, HARDWARE_ERROR, 0x00, 0x00},
+ // Device fault Hardware error
/* ICRC|ABRT */ /* NB: ICRC & !ABRT is BBD */
- {0x84, ABORTED_COMMAND, 0x47, 0x00}, // Data CRC error SCSI parity error
+ {0x84, ABORTED_COMMAND, 0x47, 0x00},
+ // Data CRC error SCSI parity error
/* MC|ID|ABRT|TRK0|MARK */
- {0x37, NOT_READY, 0x04, 0x00}, // Unit offline Not ready
+ {0x37, NOT_READY, 0x04, 0x00},
+ // Unit offline Not ready
/* MCR|MARK */
- {0x09, NOT_READY, 0x04, 0x00}, // Unrecovered disk error Not ready
+ {0x09, NOT_READY, 0x04, 0x00},
+ // Unrecovered disk error Not ready
/* Bad address mark */
- {0x01, MEDIUM_ERROR, 0x13, 0x00}, // Address mark not found Address mark not found for data field
- /* TRK0 */
- {0x02, HARDWARE_ERROR, 0x00, 0x00}, // Track 0 not found Hardware error
+ {0x01, MEDIUM_ERROR, 0x13, 0x00},
+ // Address mark not found for data field
+ /* TRK0 - Track 0 not found */
+ {0x02, HARDWARE_ERROR, 0x00, 0x00},
+ // Hardware error
/* Abort: 0x04 is not translated here, see below */
/* Media change request */
- {0x08, NOT_READY, 0x04, 0x00}, // Media change request FIXME: faking offline
- /* SRV/IDNF */
- {0x10, ILLEGAL_REQUEST, 0x21, 0x00}, // ID not found Logical address out of range
- /* MC */
- {0x20, UNIT_ATTENTION, 0x28, 0x00}, // Media Changed Not ready to ready change, medium may have changed
- /* ECC */
- {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error
+ {0x08, NOT_READY, 0x04, 0x00},
+ // FIXME: faking offline
+ /* SRV/IDNF - ID not found */
+ {0x10, ILLEGAL_REQUEST, 0x21, 0x00},
+ // Logical address out of range
+ /* MC - Media Changed */
+ {0x20, UNIT_ATTENTION, 0x28, 0x00},
+ // Not ready to ready change, medium may have changed
+ /* ECC - Uncorrectable ECC error */
+ {0x40, MEDIUM_ERROR, 0x11, 0x04},
+ // Unrecovered read error
/* BBD - block marked bad */
- {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error
+ {0x80, MEDIUM_ERROR, 0x11, 0x04},
+ // Block marked bad Medium error, unrecovered read error
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
};
static const unsigned char stat_table[][4] = {
/* Must be first because BUSY means no other bits valid */
- {0x80, ABORTED_COMMAND, 0x47, 0x00}, // Busy, fake parity for now
- {0x20, HARDWARE_ERROR, 0x44, 0x00}, // Device fault, internal target failure
- {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now
- {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered
+ {0x80, ABORTED_COMMAND, 0x47, 0x00},
+ // Busy, fake parity for now
+ {0x40, ILLEGAL_REQUEST, 0x21, 0x04},
+ // Device ready, unaligned write command
+ {0x20, HARDWARE_ERROR, 0x44, 0x00},
+ // Device fault, internal target failure
+ {0x08, ABORTED_COMMAND, 0x47, 0x00},
+ // Timed out in xfer, fake parity for now
+ {0x04, RECOVERED_ERROR, 0x11, 0x00},
+ // Recovered ECC error Medium error, recovered
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
};
@@ -1757,7 +1792,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
((cdb[2] & 0x20) || need_sense)) {
ata_gen_passthru_sense(qc);
} else {
- if (!need_sense) {
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+ cmd->result = SAM_STAT_CHECK_CONDITION;
+ } else if (!need_sense) {
cmd->result = SAM_STAT_GOOD;
} else {
/* TODO: decide which descriptor format to use
@@ -4240,10 +4277,7 @@ int ata_sas_allocate_tag(struct ata_port *ap)
unsigned int i, tag;
for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) {
- if (ap->flags & ATA_FLAG_LOWTAG)
- tag = 1;
- else
- tag = tag < max_queue ? tag : 0;
+ tag = tag < max_queue ? tag : 0;
/* the last tag is reserved for internal command. */
if (tag == ATA_TAG_INTERNAL)