All of lore.kernel.org
 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 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.