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

From: Tejun Heo
Date: Mon Feb 22 2010 - 21:28:59 EST


Hello,

On 02/22/2010 06:28 AM, Cengiz GÃnay wrote:
> On Sat, Feb 20, 2010 at 8:01 PM, Tejun Heo <tj@xxxxxxxxxx> wrote:
>> Hmmm... So, DRQ gets cleared? That's strange. When then the 18 extra
>> bytes happen? Can you please try this one?
>
> It worked!
>
> $ lsscsi
> ...
> [4:0:0:0] cd/dvd ATAPI iHOS104 WL08 /dev/sr0
> ...
>
> I was able to read a regular DVD in the drive. According to dmesg the
> negotiated speed was down to UDMA/33, so I am not sure about the
> performance of the drive.

Hmmm.... it could be that the drive is sending more data then
requested and the state machine in the controller doesn't like that
and fails to assert IRQ on the host side. You're still getting
timeouts on 96 byte dma inquiries. Can you please this patch?

--
tejun
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 0c82d33..4ad76f1 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,24 @@ 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 */
+ return 0;
+ }
+ return 1;
+}
+
static void nv_nf2_freeze(struct ata_port *ap)
{
void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;