[PATCH] libata: improve SCSI sense data generation
Update ata_gen_ata_sense() to use desc format sense data to report the first failed block. The first failed block is read from result_tf using ata_tf_read_block() which can handle all three address formats. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
35b649fe25
commit
d25614bad6
1 changed files with 23 additions and 23 deletions
|
@ -746,53 +746,53 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
|
||||||
* ata_gen_ata_sense - generate a SCSI fixed sense block
|
* ata_gen_ata_sense - generate a SCSI fixed sense block
|
||||||
* @qc: Command that we are erroring out
|
* @qc: Command that we are erroring out
|
||||||
*
|
*
|
||||||
* Leverage ata_to_sense_error() to give us the codes. Fit our
|
* Generate sense block for a failed ATA command @qc. Descriptor
|
||||||
* LBA in here if there's room.
|
* format is used to accomodate LBA48 block address.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* None.
|
* None.
|
||||||
*/
|
*/
|
||||||
static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
|
static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
|
struct ata_device *dev = qc->dev;
|
||||||
struct scsi_cmnd *cmd = qc->scsicmd;
|
struct scsi_cmnd *cmd = qc->scsicmd;
|
||||||
struct ata_taskfile *tf = &qc->result_tf;
|
struct ata_taskfile *tf = &qc->result_tf;
|
||||||
unsigned char *sb = cmd->sense_buffer;
|
unsigned char *sb = cmd->sense_buffer;
|
||||||
|
unsigned char *desc = sb + 8;
|
||||||
int verbose = qc->ap->ops->error_handler == NULL;
|
int verbose = qc->ap->ops->error_handler == NULL;
|
||||||
|
u64 block;
|
||||||
|
|
||||||
memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
|
memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
|
||||||
|
|
||||||
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
|
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
|
||||||
|
|
||||||
/*
|
/* sense data is current and format is descriptor */
|
||||||
* Use ata_to_sense_error() to map status register bits
|
sb[0] = 0x72;
|
||||||
|
|
||||||
|
/* Use ata_to_sense_error() to map status register bits
|
||||||
* onto sense key, asc & ascq.
|
* onto sense key, asc & ascq.
|
||||||
*/
|
*/
|
||||||
if (qc->err_mask ||
|
if (qc->err_mask ||
|
||||||
tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
|
tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
|
||||||
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
|
||||||
&sb[2], &sb[12], &sb[13], verbose);
|
&sb[1], &sb[2], &sb[3], verbose);
|
||||||
sb[2] &= 0x0f;
|
sb[1] &= 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb[0] = 0x70;
|
block = ata_tf_read_block(&qc->result_tf, dev);
|
||||||
sb[7] = 0x0a;
|
|
||||||
|
|
||||||
if (tf->flags & ATA_TFLAG_LBA48) {
|
/* information sense data descriptor */
|
||||||
/* TODO: find solution for LBA48 descriptors */
|
sb[7] = 12;
|
||||||
}
|
desc[0] = 0x00;
|
||||||
|
desc[1] = 10;
|
||||||
|
|
||||||
else if (tf->flags & ATA_TFLAG_LBA) {
|
desc[2] |= 0x80; /* valid */
|
||||||
/* A small (28b) LBA will fit in the 32b info field */
|
desc[6] = block >> 40;
|
||||||
sb[0] |= 0x80; /* set valid bit */
|
desc[7] = block >> 32;
|
||||||
sb[3] = tf->device & 0x0f;
|
desc[8] = block >> 24;
|
||||||
sb[4] = tf->lbah;
|
desc[9] = block >> 16;
|
||||||
sb[5] = tf->lbam;
|
desc[10] = block >> 8;
|
||||||
sb[6] = tf->lbal;
|
desc[11] = block;
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
/* TODO: C/H/S */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ata_scsi_sdev_config(struct scsi_device *sdev)
|
static void ata_scsi_sdev_config(struct scsi_device *sdev)
|
||||||
|
|
Reference in a new issue