Re: sata_nv times out for BD-ROM iHOS104-08

From: Tejun Heo
Date: Tue Mar 02 2010 - 06:37:15 EST


Hello,

On 03/01/2010 02:24 AM, Cengiz GÃnay wrote:
> Before and after the swncq-atapi-pio patch I still get awful read
> times from the BD-ROM drive:
>
> $ time dd if=/dev/sr0 of=/dev/null bs=64k count=1024
> 67108864 bytes (67 MB) copied, 106.945 seconds, 628 kB/s
> => real 1m46.977s

Hmmm... the drive is timing out even on 4k READ10's. This shouldn't
really be happening. Can you please try this one?

--
tejun
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 0c82d33..84d3eba 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -307,6 +307,7 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);

static int nv_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
+static int nv_check_atapi_dma(struct ata_queued_cmd *qc);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
static void nv_ck804_freeze(struct ata_port *ap);
@@ -470,6 +471,7 @@ static struct ata_port_operations nv_generic_ops = {
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
.hardreset = nv_hardreset,
+ .check_atapi_dma = nv_check_atapi_dma,
};

static struct ata_port_operations nv_nf2_ops = {
@@ -585,7 +587,7 @@ static const struct ata_port_info nv_port_info[] = {
/* SWNCQ */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_NCQ,
+ ATA_FLAG_NCQ | ATA_FLAG_PIO_POLLING,
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
@@ -1614,6 +1616,25 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
return -EAGAIN;
}

+#include <scsi/scsi_cmnd.h>
+static int nv_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ /* Whitelist commands that may use DMA. */
+ switch (qc->scsicmd->cmnd[0]) {
+ case WRITE_12:
+ case WRITE_10:
+ case WRITE_6:
+ case READ_12:
+ case READ_10:
+ case READ_6:
+ case 0xad: /* READ_DVD_STRUCTURE */
+ case 0xbe: /* READ_CD */
+ if (ata_qc_raw_nbytes(qc) > 4096)
+ return 0;
+ }
+ return 1;
+}
+
static void nv_nf2_freeze(struct ata_port *ap)
{
void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;