linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] libata PIO fixes (revised)
@ 2005-08-12  6:09 Albert Lee
  2005-08-12  6:15 ` [PATCH 1/2] libata ata_data_xfer() fix Albert Lee
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Albert Lee @ 2005-08-12  6:09 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE Linux, Bartlomiej Zolnierkiewicz, Doug Maxey

Jeff,

The PIO fixes revised according to the previous reviews.

1/2 pio1.diff:
   - Modify ata_mmio_data_xfer() and ata_pio_data_xfer() to handle buffer with odd length.

2/2 pio2.diff:
   - Modify __atapi_pio_bytes() to handle the case where device returns/needs extra data.

(Patch diff'ed against 2.6.13-rc6 tree, 7d69fa6266770eeb6317eddd46b64456e8a515bf)

Tested ok on x86 with Promise PDC20275 and LG DVD-Multi drive.

For your review and advice, thanks.

Albert



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] libata ata_data_xfer() fix
  2005-08-12  6:09 [PATCH 0/2] libata PIO fixes (revised) Albert Lee
@ 2005-08-12  6:15 ` Albert Lee
  2005-08-12  6:17 ` [PATCH 2/2] libata handle the case when device returns/needs extra data Albert Lee
  2005-08-12  6:45 ` [PATCH 0/2] libata PIO fixes (revised) Jeff Garzik
  2 siblings, 0 replies; 4+ messages in thread
From: Albert Lee @ 2005-08-12  6:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE Linux, Bartlomiej Zolnierkiewicz, Doug Maxey

[-- Attachment #1: Type: text/plain, Size: 354 bytes --]

Jeff,

PATCH 1/2: ata_data_xfer() fix

Changes:
   - Modify ata_mmio_data_xfer() and ata_pio_data_xfer() to handle odd-lengthed buffer.
   - Add some function comments

This patch does not reuse ap->pad as alignment buffer since
using local variable seems good enough.

For your review, thanks.

Albert

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>



[-- Attachment #2: pio1.diff --]
[-- Type: text/plain, Size: 3957 bytes --]

--- linux/drivers/scsi/libata-core.c	2005-08-12 10:31:52.000000000 +0800
+++ 01_align/drivers/scsi/libata-core.c	2005-08-12 11:14:45.000000000 +0800
@@ -2519,6 +2519,20 @@
 #endif /* __BIG_ENDIAN */
 }
 
+/**
+ *	ata_mmio_data_xfer - Transfer data by MMIO
+ *	@ap: port to read/write
+ *	@buf: data buffer
+ *	@buflen: buffer length
+ *	@do_write: read/write
+ *
+ *	Transfer data from/to the device data register by MMIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
 			       unsigned int buflen, int write_data)
 {
@@ -2527,6 +2541,7 @@
 	u16 *buf16 = (u16 *) buf;
 	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
 
+	/* Transfer multiple of 2 bytes */
 	if (write_data) {
 		for (i = 0; i < words; i++)
 			writew(le16_to_cpu(buf16[i]), mmio);
@@ -2534,19 +2549,76 @@
 		for (i = 0; i < words; i++)
 			buf16[i] = cpu_to_le16(readw(mmio));
 	}
+
+	/* Transfer trailing 1 byte, if any. */
+	if (unlikely(buflen & 0x01)) {
+		u16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (write_data) {
+			memcpy(align_buf, trailing_buf, 1);
+			writew(le16_to_cpu(align_buf[0]), mmio);
+		} else {
+			align_buf[0] = cpu_to_le16(readw(mmio));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
 }
 
+/**
+ *	ata_pio_data_xfer - Transfer data by PIO
+ *	@ap: port to read/write
+ *	@buf: data buffer
+ *	@buflen: buffer length
+ *	@do_write: read/write
+ *
+ *	Transfer data from/to the device data register by PIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
 			      unsigned int buflen, int write_data)
 {
-	unsigned int dwords = buflen >> 1;
+	unsigned int words = buflen >> 1;
 
+	/* Transfer multiple of 2 bytes */
 	if (write_data)
-		outsw(ap->ioaddr.data_addr, buf, dwords);
+		outsw(ap->ioaddr.data_addr, buf, words);
 	else
-		insw(ap->ioaddr.data_addr, buf, dwords);
+		insw(ap->ioaddr.data_addr, buf, words);
+
+	/* Transfer trailing 1 byte, if any. */
+	if (unlikely(buflen & 0x01)) {
+		u16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (write_data) {
+			memcpy(align_buf, trailing_buf, 1);
+			outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+		} else {
+			align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
 }
 
+/**
+ *	ata_data_xfer - Transfer data from/to the data register.
+ *	@ap: port to read/write
+ *	@buf: data buffer
+ *	@buflen: buffer length
+ *	@do_write: read/write
+ *
+ *	Transfer data from/to the device data register.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
 			  unsigned int buflen, int do_write)
 {
@@ -2556,6 +2628,16 @@
 		ata_pio_data_xfer(ap, buf, buflen, do_write);
 }
 
+/**
+ *	ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
+ *	@qc: Command on going
+ *
+ *	Transfer ATA_SECT_SIZE of data from/to the ATA device.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
 static void ata_pio_sector(struct ata_queued_cmd *qc)
 {
 	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2594,6 +2676,18 @@
 	kunmap(page);
 }
 
+/**
+ *	__atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *	@qc: Command on going
+ *	@bytes: number of bytes
+ *
+ *	Transfer Transfer data from/to the ATAPI device.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
 {
 	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2645,6 +2739,17 @@
 	}
 }
 
+/**
+ *	atapi_pio_bytes - Transfer data from/to the ATAPI device.
+ *	@qc: Command on going
+ *
+ *	Transfer Transfer data from/to the ATAPI device.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ */
+
 static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] libata handle the case when device returns/needs extra data
  2005-08-12  6:09 [PATCH 0/2] libata PIO fixes (revised) Albert Lee
  2005-08-12  6:15 ` [PATCH 1/2] libata ata_data_xfer() fix Albert Lee
@ 2005-08-12  6:17 ` Albert Lee
  2005-08-12  6:45 ` [PATCH 0/2] libata PIO fixes (revised) Jeff Garzik
  2 siblings, 0 replies; 4+ messages in thread
From: Albert Lee @ 2005-08-12  6:17 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE Linux, Bartlomiej Zolnierkiewicz, Doug Maxey

[-- Attachment #1: Type: text/plain, Size: 394 bytes --]

Jeff,

PATCH 2/2:

Description:
   Sometimes the device returns/needs extra data than expected.

Changes:
   Modify __atapi_pio_bytes() to handle the case where device returns/needs extra data.
     - for read case, discard trailing data from the device
     - for write case, padding zero data to the device

For your review, thanks.

Albert

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>



[-- Attachment #2: pio2.diff --]
[-- Type: text/plain, Size: 1240 bytes --]

--- 01_align/drivers/scsi/libata-core.c	2005-08-12 11:14:45.000000000 +0800
+++ 02_extra_data/drivers/scsi/libata-core.c	2005-08-12 11:14:04.000000000 +0800
@@ -2697,10 +2697,33 @@
 	unsigned char *buf;
 	unsigned int offset, count;
 
-	if (qc->curbytes == qc->nbytes - bytes)
+	if (qc->curbytes + bytes >= qc->nbytes)
 		ap->pio_task_state = PIO_ST_LAST;
 
 next_sg:
+	if (unlikely(qc->cursg >= qc->n_elem)) {
+		/* 
+		 * The end of qc->sg is reached and the device expects
+		 * more data to transfer. In order not to overrun qc->sg
+		 * and fulfill length specified in the byte count register,
+		 *    - for read case, discard trailing data from the device
+		 *    - for write case, padding zero data to the device
+		 */
+		u16 pad_buf[1] = { 0 };
+		unsigned int words = bytes >> 1;
+		unsigned int i;
+
+		if (words) /* warning if bytes > 1 */
+			printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+			       ap->id, bytes);
+
+		for (i = 0; i < words; i++)
+			ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+
+		ap->pio_task_state = PIO_ST_LAST;
+		return;
+	}
+
 	sg = &qc->sg[qc->cursg];
 
 	page = sg->page;
@@ -2734,9 +2757,8 @@
 
 	kunmap(page);
 
-	if (bytes) {
+	if (bytes)
 		goto next_sg;
-	}
 }
 
 /**

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] libata PIO fixes (revised)
  2005-08-12  6:09 [PATCH 0/2] libata PIO fixes (revised) Albert Lee
  2005-08-12  6:15 ` [PATCH 1/2] libata ata_data_xfer() fix Albert Lee
  2005-08-12  6:17 ` [PATCH 2/2] libata handle the case when device returns/needs extra data Albert Lee
@ 2005-08-12  6:45 ` Jeff Garzik
  2 siblings, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2005-08-12  6:45 UTC (permalink / raw)
  To: Albert Lee; +Cc: IDE Linux, Bartlomiej Zolnierkiewicz, Doug Maxey

Albert Lee wrote:
> Jeff,
> 
> The PIO fixes revised according to the previous reviews.
> 
> 1/2 pio1.diff:
>   - Modify ata_mmio_data_xfer() and ata_pio_data_xfer() to handle buffer 
> with odd length.
> 
> 2/2 pio2.diff:
>   - Modify __atapi_pio_bytes() to handle the case where device 
> returns/needs extra data.

Applied both patches, thanks much.

	Jeff




^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-08-12  6:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-12  6:09 [PATCH 0/2] libata PIO fixes (revised) Albert Lee
2005-08-12  6:15 ` [PATCH 1/2] libata ata_data_xfer() fix Albert Lee
2005-08-12  6:17 ` [PATCH 2/2] libata handle the case when device returns/needs extra data Albert Lee
2005-08-12  6:45 ` [PATCH 0/2] libata PIO fixes (revised) Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).