From 7a801184fa480e11e6431f184a5bdf31f63326fb Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 17 Jan 2007 12:32:12 -0600 Subject: libata: Fixup n_elem initialization Fixup the inialization of qc->n_elem. It currently gets initialized to 1 for commands that do not transfer any data. Fix this by initializing n_elem to 0 and only setting to 1 in ata_scsi_qc_new when there is data to transfer. This fixes some problems seen with SATA devices attached to ipr adapters. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata/libata-scsi.c') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 836947da5b1..7cc5a4a910a 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -372,7 +372,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, if (cmd->use_sg) { qc->__sg = (struct scatterlist *) cmd->request_buffer; qc->n_elem = cmd->use_sg; - } else { + } else if (cmd->request_bufflen) { qc->__sg = &qc->sgent; qc->n_elem = 1; } -- cgit From af068bd1debcc76c1bc265aa01401901bf0067ed Mon Sep 17 00:00:00 2001 From: David Milburn Date: Tue, 30 Jan 2007 00:59:15 -0800 Subject: libata-scsi: ata_task_ioctl should return ATA registers from sense data User applications using the HDIO_DRIVE_TASK ioctl through libata expect specific ATA registers to be returned to userspace. Verified that ata_task_ioctl correctly returns register values to the smartctl application. Signed-off-by: David Milburn Acked-by: Tejun Heo Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 51 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) (limited to 'drivers/ata/libata-scsi.c') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7cc5a4a910a..d151cf057ef 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -273,8 +273,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) { int rc = 0; u8 scsi_cmd[MAX_COMMAND_SIZE]; - u8 args[7]; - struct scsi_sense_hdr sshdr; + u8 args[7], *sensebuf = NULL; + int cmd_result; if (arg == NULL) return -EINVAL; @@ -282,10 +282,14 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) if (copy_from_user(args, arg, sizeof(args))) return -EFAULT; + sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); + if (!sensebuf) + return -ENOMEM; + memset(scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd[0] = ATA_16; scsi_cmd[1] = (3 << 1); /* Non-data */ - /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ + scsi_cmd[2] = 0x20; /* cc but no off.line or data xfer */ scsi_cmd[4] = args[1]; scsi_cmd[6] = args[2]; scsi_cmd[8] = args[3]; @@ -295,11 +299,46 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) /* Good values for timeout and retries? Values below from scsi_ioctl_send_command() for default case... */ - if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr, - (10*HZ), 5)) + cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0, + sensebuf, (10*HZ), 5, 0); + + if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ + u8 *desc = sensebuf + 8; + cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ + + /* If we set cc then ATA pass-through will cause a + * check condition even if no error. Filter that. */ + if (cmd_result & SAM_STAT_CHECK_CONDITION) { + struct scsi_sense_hdr sshdr; + scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, + &sshdr); + if (sshdr.sense_key==0 && + sshdr.asc==0 && sshdr.ascq==0) + cmd_result &= ~SAM_STAT_CHECK_CONDITION; + } + + /* Send userspace ATA registers */ + if (sensebuf[0] == 0x72 && /* format is "descriptor" */ + desc[0] == 0x09) {/* code is "ATA Descriptor" */ + args[0] = desc[13]; /* status */ + args[1] = desc[3]; /* error */ + args[2] = desc[5]; /* sector count (0:7) */ + args[3] = desc[7]; /* lbal */ + args[4] = desc[9]; /* lbam */ + args[5] = desc[11]; /* lbah */ + args[6] = desc[12]; /* select */ + if (copy_to_user(arg, args, sizeof(args))) + rc = -EFAULT; + } + } + + if (cmd_result) { rc = -EIO; + goto error; + } - /* Need code to retrieve data from check condition? */ + error: + kfree(sensebuf); return rc; } -- cgit From 78981a7c6c34bddbb90da72cf6ce10953e84aad8 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Tue, 30 Jan 2007 00:59:18 -0800 Subject: libata: fix translation for START STOP UNIT libata's SCSI translation for the SCSI START STOP UNIT command with the START bit clear (i.e. stopping the drive) appears to be incorrect. It sends an ATA STANDBY command with the time period set to 0, which the code comment says means "now", but the ATA standard says this means disable the standby timer, which effectively does nothing. Change this to issue a STANDBY IMMEDIATE command which will actually spin the drive down. The SAT (SCSI/ATA Translation) standard revision 9 concurs with this choice. Signed-off-by: Robert Hancock Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/ata/libata-scsi.c') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index d151cf057ef..73902d33576 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1022,11 +1022,10 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) } tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ - } else { - tf->nsect = 0; /* time period value (0 implies now) */ - tf->command = ATA_CMD_STANDBY; - /* Consider: ATA STANDBY IMMEDIATE command */ - } + } else + /* Issue ATA STANDBY IMMEDIATE command */ + tf->command = ATA_CMD_STANDBYNOW1; + /* * Standby and Idle condition timers could be implemented but that * would require libata to implement the Power condition mode page -- cgit