diff options
author | Tejun Heo <htejun@gmail.com> | 2008-04-30 03:35:14 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-06 11:40:55 -0400 |
commit | b3f677e501a494aa1582d4ff35fb3ac6f0a59b08 (patch) | |
tree | 07742b58e6ad35add7cefc5027a87a25e72bb8d1 /drivers | |
parent | 049e8e04986bde66df9648d88d0960ab4cbd6992 (diff) |
sata_inic162x: use IDMA for ATAPI commands
Use IDMA for ATAPI commands. Write and some misc commands time out
when executed using ATAPI_PROT_DMA but ATAPI_PROT_PIO works fine. As
PIO is driven by DMA too, it doesn't make any noticeable difference
for native SATA devices. inic_check_atapi_dma() is implemented to
force PIO for those ATAPI commands.
After this change, sata_inic162x issues all commands using IDMA.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_inic162x.c | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 579154c27902..cdae435620f6 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c | |||
@@ -192,7 +192,8 @@ struct inic_prd { | |||
192 | 192 | ||
193 | struct inic_pkt { | 193 | struct inic_pkt { |
194 | struct inic_cpb cpb; | 194 | struct inic_cpb cpb; |
195 | struct inic_prd prd[LIBATA_MAX_PRD]; | 195 | struct inic_prd prd[LIBATA_MAX_PRD + 1]; /* + 1 for cdb */ |
196 | u8 cdb[ATAPI_CDB_LEN]; | ||
196 | } __packed; | 197 | } __packed; |
197 | 198 | ||
198 | struct inic_host_priv { | 199 | struct inic_host_priv { |
@@ -361,23 +362,18 @@ static void inic_host_intr(struct ata_port *ap) | |||
361 | goto spurious; | 362 | goto spurious; |
362 | } | 363 | } |
363 | 364 | ||
364 | if (!ata_is_atapi(qc->tf.protocol)) { | 365 | if (likely(idma_stat & IDMA_STAT_DONE)) { |
365 | if (likely(idma_stat & IDMA_STAT_DONE)) { | 366 | inic_stop_idma(ap); |
366 | inic_stop_idma(ap); | ||
367 | 367 | ||
368 | /* Depending on circumstances, device error | 368 | /* Depending on circumstances, device error |
369 | * isn't reported by IDMA, check it explicitly. | 369 | * isn't reported by IDMA, check it explicitly. |
370 | */ | 370 | */ |
371 | if (unlikely(readb(port_base + PORT_TF_COMMAND) & | 371 | if (unlikely(readb(port_base + PORT_TF_COMMAND) & |
372 | (ATA_DF | ATA_ERR))) | 372 | (ATA_DF | ATA_ERR))) |
373 | qc->err_mask |= AC_ERR_DEV; | 373 | qc->err_mask |= AC_ERR_DEV; |
374 | 374 | ||
375 | ata_qc_complete(qc); | 375 | ata_qc_complete(qc); |
376 | return; | 376 | return; |
377 | } | ||
378 | } else { | ||
379 | if (likely(ata_sff_host_intr(ap, qc))) | ||
380 | return; | ||
381 | } | 377 | } |
382 | 378 | ||
383 | spurious: | 379 | spurious: |
@@ -421,6 +417,19 @@ static irqreturn_t inic_interrupt(int irq, void *dev_instance) | |||
421 | return IRQ_RETVAL(handled); | 417 | return IRQ_RETVAL(handled); |
422 | } | 418 | } |
423 | 419 | ||
420 | static int inic_check_atapi_dma(struct ata_queued_cmd *qc) | ||
421 | { | ||
422 | /* For some reason ATAPI_PROT_DMA doesn't work for some | ||
423 | * commands including writes and other misc ops. Use PIO | ||
424 | * protocol instead, which BTW is driven by the DMA engine | ||
425 | * anyway, so it shouldn't make much difference for native | ||
426 | * SATA devices. | ||
427 | */ | ||
428 | if (atapi_cmd_type(qc->cdb[0]) == READ) | ||
429 | return 0; | ||
430 | return 1; | ||
431 | } | ||
432 | |||
424 | static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc) | 433 | static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc) |
425 | { | 434 | { |
426 | struct scatterlist *sg; | 435 | struct scatterlist *sg; |
@@ -452,20 +461,21 @@ static void inic_qc_prep(struct ata_queued_cmd *qc) | |||
452 | struct inic_prd *prd = pkt->prd; | 461 | struct inic_prd *prd = pkt->prd; |
453 | bool is_atapi = ata_is_atapi(qc->tf.protocol); | 462 | bool is_atapi = ata_is_atapi(qc->tf.protocol); |
454 | bool is_data = ata_is_data(qc->tf.protocol); | 463 | bool is_data = ata_is_data(qc->tf.protocol); |
464 | unsigned int cdb_len = 0; | ||
455 | 465 | ||
456 | VPRINTK("ENTER\n"); | 466 | VPRINTK("ENTER\n"); |
457 | 467 | ||
458 | if (is_atapi) | 468 | if (is_atapi) |
459 | return; | 469 | cdb_len = qc->dev->cdb_len; |
460 | 470 | ||
461 | /* prepare packet, based on initio driver */ | 471 | /* prepare packet, based on initio driver */ |
462 | memset(pkt, 0, sizeof(struct inic_pkt)); | 472 | memset(pkt, 0, sizeof(struct inic_pkt)); |
463 | 473 | ||
464 | cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN; | 474 | cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN; |
465 | if (is_data) | 475 | if (is_atapi || is_data) |
466 | cpb->ctl_flags |= CPB_CTL_DATA; | 476 | cpb->ctl_flags |= CPB_CTL_DATA; |
467 | 477 | ||
468 | cpb->len = cpu_to_le32(qc->nbytes); | 478 | cpb->len = cpu_to_le32(qc->nbytes + cdb_len); |
469 | cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd)); | 479 | cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd)); |
470 | 480 | ||
471 | cpb->device = qc->tf.device; | 481 | cpb->device = qc->tf.device; |
@@ -486,6 +496,18 @@ static void inic_qc_prep(struct ata_queued_cmd *qc) | |||
486 | cpb->command = qc->tf.command; | 496 | cpb->command = qc->tf.command; |
487 | /* don't load ctl - dunno why. it's like that in the initio driver */ | 497 | /* don't load ctl - dunno why. it's like that in the initio driver */ |
488 | 498 | ||
499 | /* setup PRD for CDB */ | ||
500 | if (is_atapi) { | ||
501 | memcpy(pkt->cdb, qc->cdb, ATAPI_CDB_LEN); | ||
502 | prd->mad = cpu_to_le32(pp->pkt_dma + | ||
503 | offsetof(struct inic_pkt, cdb)); | ||
504 | prd->len = cpu_to_le16(cdb_len); | ||
505 | prd->flags = PRD_CDB | PRD_WRITE; | ||
506 | if (!is_data) | ||
507 | prd->flags |= PRD_END; | ||
508 | prd++; | ||
509 | } | ||
510 | |||
489 | /* setup sg table */ | 511 | /* setup sg table */ |
490 | if (is_data) | 512 | if (is_data) |
491 | inic_fill_sg(prd, qc); | 513 | inic_fill_sg(prd, qc); |
@@ -498,16 +520,12 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc) | |||
498 | struct ata_port *ap = qc->ap; | 520 | struct ata_port *ap = qc->ap; |
499 | void __iomem *port_base = inic_port_base(ap); | 521 | void __iomem *port_base = inic_port_base(ap); |
500 | 522 | ||
501 | if (!ata_is_atapi(qc->tf.protocol)) { | 523 | /* fire up the ADMA engine */ |
502 | /* fire up the ADMA engine */ | 524 | writew(HCTL_FTHD0, port_base + HOST_CTL); |
503 | writew(HCTL_FTHD0, port_base + HOST_CTL); | 525 | writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL); |
504 | writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL); | 526 | writeb(0, port_base + PORT_CPB_PTQFIFO); |
505 | writeb(0, port_base + PORT_CPB_PTQFIFO); | ||
506 | |||
507 | return 0; | ||
508 | } | ||
509 | 527 | ||
510 | return ata_sff_qc_issue(qc); | 528 | return 0; |
511 | } | 529 | } |
512 | 530 | ||
513 | static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | 531 | static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf) |
@@ -698,6 +716,7 @@ static int inic_port_start(struct ata_port *ap) | |||
698 | static struct ata_port_operations inic_port_ops = { | 716 | static struct ata_port_operations inic_port_ops = { |
699 | .inherits = &ata_sff_port_ops, | 717 | .inherits = &ata_sff_port_ops, |
700 | 718 | ||
719 | .check_atapi_dma = inic_check_atapi_dma, | ||
701 | .qc_prep = inic_qc_prep, | 720 | .qc_prep = inic_qc_prep, |
702 | .qc_issue = inic_qc_issue, | 721 | .qc_issue = inic_qc_issue, |
703 | .qc_fill_rtf = inic_qc_fill_rtf, | 722 | .qc_fill_rtf = inic_qc_fill_rtf, |
@@ -717,12 +736,6 @@ static struct ata_port_operations inic_port_ops = { | |||
717 | }; | 736 | }; |
718 | 737 | ||
719 | static struct ata_port_info inic_port_info = { | 738 | static struct ata_port_info inic_port_info = { |
720 | /* For some reason, ATAPI_PROT_PIO is broken on this | ||
721 | * controller, and no, PIO_POLLING does't fix it. It somehow | ||
722 | * manages to report the wrong ireason and ignoring ireason | ||
723 | * results in machine lock up. Tell libata to always prefer | ||
724 | * DMA. | ||
725 | */ | ||
726 | .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, | 739 | .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, |
727 | .pio_mask = 0x1f, /* pio0-4 */ | 740 | .pio_mask = 0x1f, /* pio0-4 */ |
728 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 741 | .mwdma_mask = 0x07, /* mwdma0-2 */ |