linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3/3] libata - Query the driver for ATAPI DMA support
@ 2004-12-15 10:05 Albert Lee
  0 siblings, 0 replies; 4+ messages in thread
From: Albert Lee @ 2004-12-15 10:05 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE Linux, Doug Maxey

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

Hi, Jeff:

> After some testing, it seems that some PATA host adapter (ex. pdc20275) cannot 
> work reliably with specific request buffer sizes under ATAPI DMA mode.
>
> Detailed test result:
> 4096, 2048, 1024, 512, 256: OK
> 384, 257, 255, 128, 96, 64, 32:  failed (irq lost)
> 
>  It seems multiple of 256 bytes are the safe ATAPI DMA buffer sizes to use.
>

Attached please find the patch to fix the pdc2027x ATAPI DMA problem.
(The patch is against libata-dev-2.6 tree.)

Changes:
1. Add a callback function "check_atapi_dma()" to ata_port_operations such that libata core
can ask the driver: "Can this command be processed in ATAPI DMA mode safely? " 
when the the command is received.
2. ATAPI DMA is off by default if the callback function is not provided by the driver

Albert

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
---
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-core.c libata-dev-2.6/drivers/scsi/libata-core.c
--- libata-dev-2.6-ori/drivers/scsi/libata-core.c 2004-12-15 16:10:30.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-core.c 2004-12-15 16:15:01.000000000 +0800
@@ -1947,7 +1947,24 @@
  if (idx)
   ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
+/**
+ * ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+ * @qc: Metadata associated with taskfile to check
+ *
+ * LOCKING:
+ * RETURNS: 0 when ATAPI DMA can be used
+ *               nonzero otherwise
+ */
+int ata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ int rc = 1; /* Turn off ATAPI DMA by default */
+
+ if (ap->ops->check_atapi_dma)
+  rc = ap->ops->check_atapi_dma(qc);
 
+ return rc;
+}
 /**
  * ata_qc_prep - Prepare taskfile for submission
  * @qc: Metadata associated with taskfile to be prepared
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata.h libata-dev-2.6/drivers/scsi/libata.h
--- libata-dev-2.6-ori/drivers/scsi/libata.h 2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata.h 2004-12-15 16:36:55.000000000 +0800
@@ -38,6 +38,7 @@
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
           struct ata_device *dev);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
+extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-scsi.c libata-dev-2.6/drivers/scsi/libata-scsi.c
--- libata-dev-2.6-ori/drivers/scsi/libata-scsi.c 2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-scsi.c 2004-12-15 16:15:59.000000000 +0800
@@ -1558,6 +1558,11 @@
  int using_pio = (dev->flags & ATA_DFLAG_PIO);
  int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
 
+ if (!using_pio)
+  /* Check whether ATAPI DMA is safe */
+  if (ata_check_atapi_dma(qc))
+   using_pio = 1;
+
  memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
 
  qc->complete_fn = atapi_qc_complete;
diff -Nru libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c libata-dev-2.6/drivers/scsi/pata_pdc2027x.c
--- libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c 2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/pata_pdc2027x.c 2004-12-15 16:21:00.000000000 +0800
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME "pata_pdc2027x"
-#define DRV_VERSION "0.53"
+#define DRV_VERSION "0.54"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -51,6 +51,7 @@
 static void pdc2027x_phy_reset(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
 
 /* 
  * ATA Timing Tables based on 133MHz controller clock.
@@ -141,6 +142,7 @@
 
  .phy_reset  = pdc2027x_phy_reset,   
 
+ .check_atapi_dma = pdc2027x_check_atapi_dma,
  .bmdma_setup            = ata_bmdma_setup,
  .bmdma_start            = ata_bmdma_start,
  .qc_prep  = ata_qc_prep,
@@ -377,6 +379,27 @@
  }
 }
 /**
+ * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
+ * @qc: Metadata associated with taskfile to check
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ *
+ * RETURNS: 0 when ATAPI DMA can be used
+ *               1 otherwise
+ */
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ int rc = 0;
+
+ /* pdc2027x can only do ATAPI DMA for specific buffer size */
+ if (cmd->request_bufflen % 256)
+  rc = 1;
+
+ return rc;
+}
+/**
  * adjust_pll - Adjust the PLL input clock in Hz.
  *
  * @pdc_controller: controller specific information
diff -Nru libata-dev-2.6-ori/include/linux/libata.h libata-dev-2.6/include/linux/libata.h
--- libata-dev-2.6-ori/include/linux/libata.h 2004-11-30 12:52:42.000000000 +0800
+++ libata-dev-2.6/include/linux/libata.h 2004-12-15 16:17:41.000000000 +0800
@@ -339,6 +339,8 @@
  void (*phy_reset) (struct ata_port *ap);
  void (*post_set_mode) (struct ata_port *ap);
 
+ int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+
  void (*bmdma_setup) (struct ata_queued_cmd *qc);
  void (*bmdma_start) (struct ata_queued_cmd *qc);
 


[-- Attachment #2: atapi_dma_check.patch --]
[-- Type: application/octet-stream, Size: 4572 bytes --]

diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-core.c libata-dev-2.6/drivers/scsi/libata-core.c
--- libata-dev-2.6-ori/drivers/scsi/libata-core.c	2004-12-15 16:10:30.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-core.c	2004-12-15 16:15:01.000000000 +0800
@@ -1947,7 +1947,24 @@
 	if (idx)
 		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
+/**
+ *	ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+ *	@qc: Metadata associated with taskfile to check
+ *
+ *	LOCKING:
+ *	RETURNS: 0 when ATAPI DMA can be used
+ *               nonzero otherwise
+ */
+int ata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	int rc = 1; /* Turn off ATAPI DMA by default */
+
+	if (ap->ops->check_atapi_dma)
+		rc = ap->ops->check_atapi_dma(qc);
 
+	return rc;
+}
 /**
  *	ata_qc_prep - Prepare taskfile for submission
  *	@qc: Metadata associated with taskfile to be prepared
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata.h libata-dev-2.6/drivers/scsi/libata.h
--- libata-dev-2.6-ori/drivers/scsi/libata.h	2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata.h	2004-12-15 16:36:55.000000000 +0800
@@ -38,6 +38,7 @@
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
+extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-scsi.c libata-dev-2.6/drivers/scsi/libata-scsi.c
--- libata-dev-2.6-ori/drivers/scsi/libata-scsi.c	2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-scsi.c	2004-12-15 16:15:59.000000000 +0800
@@ -1558,6 +1558,11 @@
 	int using_pio = (dev->flags & ATA_DFLAG_PIO);
 	int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
 
+	if (!using_pio)
+		/* Check whether ATAPI DMA is safe */
+		if (ata_check_atapi_dma(qc))
+			using_pio = 1;
+
 	memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
 
 	qc->complete_fn = atapi_qc_complete;
diff -Nru libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c libata-dev-2.6/drivers/scsi/pata_pdc2027x.c
--- libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c	2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/pata_pdc2027x.c	2004-12-15 16:21:00.000000000 +0800
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"pata_pdc2027x"
-#define DRV_VERSION	"0.53"
+#define DRV_VERSION	"0.54"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -51,6 +51,7 @@
 static void pdc2027x_phy_reset(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
 
 /* 
  * ATA Timing Tables based on 133MHz controller clock.
@@ -141,6 +142,7 @@
 
 	.phy_reset		= pdc2027x_phy_reset,   
 
+	.check_atapi_dma	= pdc2027x_check_atapi_dma,
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
@@ -377,6 +379,27 @@
 	}
 }
 /**
+ *	pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
+ *	@qc: Metadata associated with taskfile to check
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ *
+ *	RETURNS: 0 when ATAPI DMA can be used
+ *               1 otherwise
+ */
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	int rc = 0;
+
+	/* pdc2027x can only do ATAPI DMA for specific buffer size */
+	if (cmd->request_bufflen % 256)
+		rc = 1;
+
+	return rc;
+}
+/**
  * adjust_pll - Adjust the PLL input clock in Hz.
  *
  * @pdc_controller: controller specific information
diff -Nru libata-dev-2.6-ori/include/linux/libata.h libata-dev-2.6/include/linux/libata.h
--- libata-dev-2.6-ori/include/linux/libata.h	2004-11-30 12:52:42.000000000 +0800
+++ libata-dev-2.6/include/linux/libata.h	2004-12-15 16:17:41.000000000 +0800
@@ -339,6 +339,8 @@
 	void (*phy_reset) (struct ata_port *ap);
 	void (*post_set_mode) (struct ata_port *ap);
 
+	int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+
 	void (*bmdma_setup) (struct ata_queued_cmd *qc);
 	void (*bmdma_start) (struct ata_queued_cmd *qc);
 

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

* Re: [PATCH 3/3] libata - Query the driver for ATAPI DMA support
@ 2004-12-16  5:28 Albert Lee
  2004-12-17 20:01 ` Bartlomiej Zolnierkiewicz
  2004-12-27 20:29 ` Jeff Garzik
  0 siblings, 2 replies; 4+ messages in thread
From: Albert Lee @ 2004-12-16  5:28 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: IDE Linux, Doug Maxey

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

Hi, Jeff:

> 
> > After some testing, it seems that some PATA host adapter (ex. pdc20275) cannot 
> > work reliably with specific request buffer sizes under ATAPI DMA mode.
> >
> > Detailed test result:
> > 4096, 2048, 1024, 512, 256: OK
> > 384, 257, 255, 128, 96, 64, 32:  failed (irq lost)
> > 
> >  It seems multiple of 256 bytes are the safe ATAPI DMA buffer sizes to use.
> >
> 
> Attached please find the patch to fix the pdc2027x ATAPI DMA problem.
> (The patch is against libata-dev-2.6 tree.)
> 
> Changes:
> 1. Add a callback function "check_atapi_dma()" to ata_port_operations such that libata core
> can ask the driver: "Can this command be processed in ATAPI DMA mode safely? " 
> when the the command is received.
> 2. ATAPI DMA is off by default if the callback function is not provided by the driver

    Sorry, there is a mistake in the previous patch. Revised the patch here:
If the callback function is not provided by the driver, the ATAPI DMA should be as is.
We should not turn off ATAPI DMA silently as in the previous patch. The ATAPI DMA is 
already controlled by dev->flags.

BTW, the patch isolates the ATAPI DMA workaround to the pdc20275 driver itself, not impacting libata core .
Attached please find the revised patch for your review.
 
Albert
 
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
---
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-core.c libata-dev-2.6/drivers/scsi/libata-core.c
--- libata-dev-2.6-ori/drivers/scsi/libata-core.c 2004-12-15 16:10:30.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-core.c 2004-12-16 11:33:33.000000000 +0800
@@ -1947,7 +1947,24 @@
  if (idx)
   ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
+/**
+ * ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+ * @qc: Metadata associated with taskfile to check
+ *
+ * LOCKING:
+ * RETURNS: 0 when ATAPI DMA can be used
+ *               nonzero otherwise
+ */
+int ata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ int rc = 0; /* Assume ATAPI DMA is OK by default */
+
+ if (ap->ops->check_atapi_dma)
+  rc = ap->ops->check_atapi_dma(qc);
 
+ return rc;
+}
 /**
  * ata_qc_prep - Prepare taskfile for submission
  * @qc: Metadata associated with taskfile to be prepared
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata.h libata-dev-2.6/drivers/scsi/libata.h
--- libata-dev-2.6-ori/drivers/scsi/libata.h 2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata.h 2004-12-15 16:36:55.000000000 +0800
@@ -38,6 +38,7 @@
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
           struct ata_device *dev);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
+extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-scsi.c libata-dev-2.6/drivers/scsi/libata-scsi.c
--- libata-dev-2.6-ori/drivers/scsi/libata-scsi.c 2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-scsi.c 2004-12-15 16:15:59.000000000 +0800
@@ -1558,6 +1558,11 @@
  int using_pio = (dev->flags & ATA_DFLAG_PIO);
  int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
 
+ if (!using_pio)
+  /* Check whether ATAPI DMA is safe */
+  if (ata_check_atapi_dma(qc))
+   using_pio = 1;
+
  memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
 
  qc->complete_fn = atapi_qc_complete;
diff -Nru libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c libata-dev-2.6/drivers/scsi/pata_pdc2027x.c
--- libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c 2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/pata_pdc2027x.c 2004-12-15 16:21:00.000000000 +0800
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME "pata_pdc2027x"
-#define DRV_VERSION "0.53"
+#define DRV_VERSION "0.54"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -51,6 +51,7 @@
 static void pdc2027x_phy_reset(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
 
 /* 
  * ATA Timing Tables based on 133MHz controller clock.
@@ -141,6 +142,7 @@
 
  .phy_reset  = pdc2027x_phy_reset,   
 
+ .check_atapi_dma = pdc2027x_check_atapi_dma,
  .bmdma_setup            = ata_bmdma_setup,
  .bmdma_start            = ata_bmdma_start,
  .qc_prep  = ata_qc_prep,
@@ -377,6 +379,27 @@
  }
 }
 /**
+ * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
+ * @qc: Metadata associated with taskfile to check
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ *
+ * RETURNS: 0 when ATAPI DMA can be used
+ *               1 otherwise
+ */
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ int rc = 0;
+
+ /* pdc2027x can only do ATAPI DMA for specific buffer size */
+ if (cmd->request_bufflen % 256)
+  rc = 1;
+
+ return rc;
+}
+/**
  * adjust_pll - Adjust the PLL input clock in Hz.
  *
  * @pdc_controller: controller specific information
diff -Nru libata-dev-2.6-ori/include/linux/libata.h libata-dev-2.6/include/linux/libata.h
--- libata-dev-2.6-ori/include/linux/libata.h 2004-11-30 12:52:42.000000000 +0800
+++ libata-dev-2.6/include/linux/libata.h 2004-12-15 16:17:41.000000000 +0800
@@ -339,6 +339,8 @@
  void (*phy_reset) (struct ata_port *ap);
  void (*post_set_mode) (struct ata_port *ap);
 
+ int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+
  void (*bmdma_setup) (struct ata_queued_cmd *qc);
  void (*bmdma_start) (struct ata_queued_cmd *qc);
 

[-- Attachment #2: atapi_dma_check.patch --]
[-- Type: application/octet-stream, Size: 4576 bytes --]

diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-core.c libata-dev-2.6/drivers/scsi/libata-core.c
--- libata-dev-2.6-ori/drivers/scsi/libata-core.c	2004-12-15 16:10:30.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-core.c	2004-12-16 11:33:33.000000000 +0800
@@ -1947,7 +1947,24 @@
 	if (idx)
 		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
+/**
+ *	ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+ *	@qc: Metadata associated with taskfile to check
+ *
+ *	LOCKING:
+ *	RETURNS: 0 when ATAPI DMA can be used
+ *               nonzero otherwise
+ */
+int ata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	int rc = 0; /* Assume ATAPI DMA is OK by default */
+
+	if (ap->ops->check_atapi_dma)
+		rc = ap->ops->check_atapi_dma(qc);
 
+	return rc;
+}
 /**
  *	ata_qc_prep - Prepare taskfile for submission
  *	@qc: Metadata associated with taskfile to be prepared
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata.h libata-dev-2.6/drivers/scsi/libata.h
--- libata-dev-2.6-ori/drivers/scsi/libata.h	2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata.h	2004-12-15 16:36:55.000000000 +0800
@@ -38,6 +38,7 @@
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
+extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
diff -Nru libata-dev-2.6-ori/drivers/scsi/libata-scsi.c libata-dev-2.6/drivers/scsi/libata-scsi.c
--- libata-dev-2.6-ori/drivers/scsi/libata-scsi.c	2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/libata-scsi.c	2004-12-15 16:15:59.000000000 +0800
@@ -1558,6 +1558,11 @@
 	int using_pio = (dev->flags & ATA_DFLAG_PIO);
 	int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
 
+	if (!using_pio)
+		/* Check whether ATAPI DMA is safe */
+		if (ata_check_atapi_dma(qc))
+			using_pio = 1;
+
 	memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
 
 	qc->complete_fn = atapi_qc_complete;
diff -Nru libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c libata-dev-2.6/drivers/scsi/pata_pdc2027x.c
--- libata-dev-2.6-ori/drivers/scsi/pata_pdc2027x.c	2004-11-30 12:52:28.000000000 +0800
+++ libata-dev-2.6/drivers/scsi/pata_pdc2027x.c	2004-12-15 16:21:00.000000000 +0800
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"pata_pdc2027x"
-#define DRV_VERSION	"0.53"
+#define DRV_VERSION	"0.54"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -51,6 +51,7 @@
 static void pdc2027x_phy_reset(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
 
 /* 
  * ATA Timing Tables based on 133MHz controller clock.
@@ -141,6 +142,7 @@
 
 	.phy_reset		= pdc2027x_phy_reset,   
 
+	.check_atapi_dma	= pdc2027x_check_atapi_dma,
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
@@ -377,6 +379,27 @@
 	}
 }
 /**
+ *	pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
+ *	@qc: Metadata associated with taskfile to check
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ *
+ *	RETURNS: 0 when ATAPI DMA can be used
+ *               1 otherwise
+ */
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	int rc = 0;
+
+	/* pdc2027x can only do ATAPI DMA for specific buffer size */
+	if (cmd->request_bufflen % 256)
+		rc = 1;
+
+	return rc;
+}
+/**
  * adjust_pll - Adjust the PLL input clock in Hz.
  *
  * @pdc_controller: controller specific information
diff -Nru libata-dev-2.6-ori/include/linux/libata.h libata-dev-2.6/include/linux/libata.h
--- libata-dev-2.6-ori/include/linux/libata.h	2004-11-30 12:52:42.000000000 +0800
+++ libata-dev-2.6/include/linux/libata.h	2004-12-15 16:17:41.000000000 +0800
@@ -339,6 +339,8 @@
 	void (*phy_reset) (struct ata_port *ap);
 	void (*post_set_mode) (struct ata_port *ap);
 
+	int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+
 	void (*bmdma_setup) (struct ata_queued_cmd *qc);
 	void (*bmdma_start) (struct ata_queued_cmd *qc);
 

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

* Re: [PATCH 3/3] libata - Query the driver for ATAPI DMA support
  2004-12-16  5:28 [PATCH 3/3] libata - Query the driver for ATAPI DMA support Albert Lee
@ 2004-12-17 20:01 ` Bartlomiej Zolnierkiewicz
  2004-12-27 20:29 ` Jeff Garzik
  1 sibling, 0 replies; 4+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2004-12-17 20:01 UTC (permalink / raw)
  To: Albert Lee; +Cc: Jeff Garzik, IDE Linux, Doug Maxey

On Thu, 16 Dec 2004 13:28:28 +0800, Albert Lee <albertcc@tw.ibm.com> wrote:
> Hi, Jeff:
> 
> >
> > > After some testing, it seems that some PATA host adapter (ex. pdc20275) cannot
> > > work reliably with specific request buffer sizes under ATAPI DMA mode.
> > >
> > > Detailed test result:
> > > 4096, 2048, 1024, 512, 256: OK
> > > 384, 257, 255, 128, 96, 64, 32:  failed (irq lost)
> > >
> > >  It seems multiple of 256 bytes are the safe ATAPI DMA buffer sizes to use.
> > >
> >
> > Attached please find the patch to fix the pdc2027x ATAPI DMA problem.
> > (The patch is against libata-dev-2.6 tree.)
> >
> > Changes:
> > 1. Add a callback function "check_atapi_dma()" to ata_port_operations such that libata core
> > can ask the driver: "Can this command be processed in ATAPI DMA mode safely? "
> > when the the command is received.
> > 2. ATAPI DMA is off by default if the callback function is not provided by the driver
> 
>     Sorry, there is a mistake in the previous patch. Revised the patch here:
> If the callback function is not provided by the driver, the ATAPI DMA should be as is.
> We should not turn off ATAPI DMA silently as in the previous patch. The ATAPI DMA is
> already controlled by dev->flags.
> 
> BTW, the patch isolates the ATAPI DMA workaround to the pdc20275 driver itself, not impacting libata core .
> Attached please find the revised patch for your review.

Looks fine, only one minor nitpick - it seems some newlines are missed...

> @@ -1947,7 +1947,24 @@
>   if (idx)
>    ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
>  }
> +/**

etc.

All three patches look OK.

Jeff, could you merge them if they are fine with you?
[ 1 and 2 should probably go to libata-2.6 but of course it's up to you ]

Bartlomiej

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

* Re: [PATCH 3/3] libata - Query the driver for ATAPI DMA support
  2004-12-16  5:28 [PATCH 3/3] libata - Query the driver for ATAPI DMA support Albert Lee
  2004-12-17 20:01 ` Bartlomiej Zolnierkiewicz
@ 2004-12-27 20:29 ` Jeff Garzik
  1 sibling, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2004-12-27 20:29 UTC (permalink / raw)
  To: Albert Lee; +Cc: IDE Linux, Doug Maxey, Bartlomiej Zolnierkiewicz

applied patches 1-3


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

end of thread, other threads:[~2004-12-27 20:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-16  5:28 [PATCH 3/3] libata - Query the driver for ATAPI DMA support Albert Lee
2004-12-17 20:01 ` Bartlomiej Zolnierkiewicz
2004-12-27 20:29 ` Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2004-12-15 10:05 Albert Lee

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).