All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Raubitschek <jhr@google.com>
To: Jeff Garzik <jgarzik@pobox.com>
Cc: linux-ide@vger.kernel.org
Subject: [PATCH libata-dev-2.6:passthru] passthru fixes
Date: Tue, 13 Sep 2005 07:26:36 -0700	[thread overview]
Message-ID: <20050913142636.GB5679@google.com> (raw)

Fix a few problems seen with the passthru branch:

- leaked scsi_request on buffer allocate failure
- passthru sense routines were refering to tf->command
  which is not read in tf_read, instead use drv_stat for
  status register.
- passthru sense passed back to user on ata_task_ioctl

Patch is against the current libata-dev passthru branch.

Signed-off-by: Jeff Raubitschek <jhr@google.com>

diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -116,8 +116,10 @@ int ata_cmd_ioctl(struct scsi_device *sc
 	if (args[3]) {
 		argsize = SECTOR_SIZE * args[3];
 		argbuf = kmalloc(argsize, GFP_KERNEL);
-		if (argbuf == NULL)
-			return -ENOMEM;
+		if (argbuf == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
 
 		scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
 		scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
@@ -182,6 +184,7 @@ int ata_task_ioctl(struct scsi_device *s
 	u8 scsi_cmd[MAX_COMMAND_SIZE];
 	u8 args[7];
 	struct scsi_request *sreq;
+	unsigned char *sb;
 
 	if (NULL == (void *)arg)
 		return -EINVAL;
@@ -192,7 +195,7 @@ int ata_task_ioctl(struct scsi_device *s
 	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; /* Always ask for sense data */
 	scsi_cmd[4]  = args[1];
 	scsi_cmd[6]  = args[2];
 	scsi_cmd[8]  = args[3];
@@ -211,15 +214,29 @@ int ata_task_ioctl(struct scsi_device *s
 	   from scsi_ioctl_send_command() for default case... */
 	scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
 
-	if (sreq->sr_result) {
+	sb = sreq->sr_sense_buffer;
+
+	/* Retrieve data from check condition */
+	if((sb[1] == NO_SENSE) && (sb[2] == 0) && (sb[3] == 0x1D)) {
+		unsigned char *desc= sb + 8;
+
+		args[0]=desc[13];
+		args[1]=desc[3];
+		args[2]=desc[5];
+		args[3]=desc[7];
+		args[4]=desc[9];
+		args[5]=desc[11];
+	} else if (sreq->sr_result) {
 		rc = -EIO;
 		goto error;
 	}
 
-	/* Need code to retrieve data from check condition? */
-
 error:
 	scsi_release_request(sreq);
+
+	if (rc == 0 && copy_to_user(arg, args, sizeof(args)))
+		return -EFAULT;
+
 	return rc;
 }
 
@@ -323,6 +340,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(s
  *	ata_dump_status - user friendly display of error info
  *	@id: id of the port in question
  *	@tf: ptr to filled out taskfile
+ *	@stat: ATA command/status register
  *
  *	Decode and dump the ATA error/status registers for the user so
  *	that they have some idea what really happened at the non
@@ -331,9 +349,9 @@ struct ata_queued_cmd *ata_scsi_qc_new(s
  *	LOCKING:
  *	inherited from caller
  */
-void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+void ata_dump_status(unsigned id, struct ata_taskfile *tf, u8 stat)
 {
-	u8 stat = tf->command, err = tf->feature;
+	u8 err = tf->feature;
 
 	printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
 	if (stat & ATA_BUSY) {
@@ -479,6 +497,7 @@ void ata_to_sense_error(unsigned id, u8 
 /*
  *	ata_gen_ata_desc_sense - Generate check condition sense block.
  *	@qc: Command that completed.
+ *	@stat: ATA status register
  *
  *	This function is specific to the ATA descriptor format sense
  *	block specified for the ATA pass through commands.  Regardless
@@ -489,7 +508,7 @@ void ata_to_sense_error(unsigned id, u8 
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
-void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc, u8 stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->tf;
@@ -510,10 +529,15 @@ void ata_gen_ata_desc_sense(struct ata_q
 	 * Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 */
-	if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+	if (unlikely(stat & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
 				   &sb[1], &sb[2], &sb[3]);
 		sb[1] &= 0x0f;
+	} else {
+		/* ATA PASS THROUGH INFORMATION AVAILABLE */
+		sb[1] = NO_SENSE;
+		sb[2] = 0;
+		sb[3] = 0x1D;
 	}
 
 	/*
@@ -540,7 +564,7 @@ void ata_gen_ata_desc_sense(struct ata_q
 	desc[9] = tf->lbam;
 	desc[11] = tf->lbah;
 	desc[12] = tf->device;
-	desc[13] = tf->command; /* == status reg */
+	desc[13] = stat;
 
 	/*
 	 * Fill in Extend bit, and the high order bytes
@@ -558,6 +582,7 @@ void ata_gen_ata_desc_sense(struct ata_q
 /**
  *	ata_gen_fixed_sense - generate a SCSI fixed sense block
  *	@qc: Command that we are erroring out
+ *	@stat: ATA status register
  *
  *	Leverage ata_to_sense_error() to give us the codes.  Fit our
  *	LBA in here if there's room.
@@ -565,7 +590,7 @@ void ata_gen_ata_desc_sense(struct ata_q
  *	LOCKING:
  *	inherited from caller
  */
-void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+void ata_gen_fixed_sense(struct ata_queued_cmd *qc, u8 stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->tf;
@@ -585,7 +610,7 @@ void ata_gen_fixed_sense(struct ata_queu
 	 * Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 */
-	if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+	if (unlikely(stat & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
 				   &sb[2], &sb[12], &sb[13]);
 		sb[2] &= 0x0f;
@@ -998,7 +1023,7 @@ static int ata_scsi_qc_complete(struct a
 	 */
 	if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) &&
  	    ((cmd->cmnd[2] & 0x20) || need_sense)) {
- 		ata_gen_ata_desc_sense(qc);
+ 		ata_gen_ata_desc_sense(qc, drv_stat);
 	} else {
 		if (!need_sense) {
 			cmd->result = SAM_STAT_GOOD;
@@ -1009,13 +1034,13 @@ static int ata_scsi_qc_complete(struct a
 			 * good for smaller LBA (and maybe CHS?)
 			 * devices.
 			 */
-			ata_gen_fixed_sense(qc);
+			ata_gen_fixed_sense(qc, drv_stat);
 		}
 	}
 
 	if (need_sense) {
 		/* The ata_gen_..._sense routines fill in tf */
-		ata_dump_status(qc->ap->id, &qc->tf);
+		ata_dump_status(qc->ap->id, &qc->tf, drv_stat);
 	}
 
 	qc->scsidone(cmd);

             reply	other threads:[~2005-09-13 14:26 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-13 14:26 Jeff Raubitschek [this message]
2005-09-14 12:18 ` [PATCH libata-dev-2.6:passthru] passthru fixes Jeff Garzik
2005-09-21 14:32 ` John W. Linville
2005-10-04 14:22 ` Jeff Garzik
2005-10-10 20:39   ` Mark Lord

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050913142636.GB5679@google.com \
    --to=jhr@google.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.