diff options
author | Tejun Heo <tj@kernel.org> | 2010-05-19 16:10:21 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2010-05-25 19:40:24 -0400 |
commit | c3b2889424c26f3b42962b6f39aabb4f1fd1b576 (patch) | |
tree | c131d260c18815cb84331357db75c17dabf083d8 /drivers/ata/libata-sff.c | |
parent | 37f65b8bc262a5ae4c8e58be92fe3032f0aaaf04 (diff) |
libata-sff: separate out BMDMA irq handler
Separate out BMDMA irq handler from SFF irq handler. The misnamed
host_intr() functions are renamed to ata_sff_port_intr() and
ata_bmdma_port_intr(). Common parts are factored into
__ata_sff_port_intr() and __ata_sff_interrupt() and used by sff and
bmdma interrupt routines.
All BMDMA drivers now use ata_bmdma_interrupt() or
ata_bmdma_port_intr() while all non-BMDMA SFF ones use
ata_sff_interrupt() or ata_sff_port_intr().
For now, ata_pci_sff_init_one() uses ata_bmdma_interrupt() as it's
used by both SFF and BMDMA drivers.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 208 |
1 files changed, 130 insertions, 78 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 55bc4880cbf3..bef7571a1d42 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -1469,27 +1469,27 @@ bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc) | |||
1469 | } | 1469 | } |
1470 | EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); | 1470 | EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); |
1471 | 1471 | ||
1472 | /** | 1472 | static unsigned int ata_sff_idle_irq(struct ata_port *ap) |
1473 | * ata_sff_host_intr - Handle host interrupt for given (port, task) | ||
1474 | * @ap: Port on which interrupt arrived (possibly...) | ||
1475 | * @qc: Taskfile currently active in engine | ||
1476 | * | ||
1477 | * Handle host interrupt for given queued command. Currently, | ||
1478 | * only DMA interrupts are handled. All other commands are | ||
1479 | * handled via polling with interrupts disabled (nIEN bit). | ||
1480 | * | ||
1481 | * LOCKING: | ||
1482 | * spin_lock_irqsave(host lock) | ||
1483 | * | ||
1484 | * RETURNS: | ||
1485 | * One if interrupt was handled, zero if not (shared irq). | ||
1486 | */ | ||
1487 | unsigned int ata_sff_host_intr(struct ata_port *ap, | ||
1488 | struct ata_queued_cmd *qc) | ||
1489 | { | 1473 | { |
1490 | struct ata_eh_info *ehi = &ap->link.eh_info; | 1474 | ap->stats.idle_irq++; |
1491 | u8 status, host_stat = 0; | 1475 | |
1492 | bool bmdma_stopped = false; | 1476 | #ifdef ATA_IRQ_TRAP |
1477 | if ((ap->stats.idle_irq % 1000) == 0) { | ||
1478 | ap->ops->sff_check_status(ap); | ||
1479 | if (ap->ops->sff_irq_clear) | ||
1480 | ap->ops->sff_irq_clear(ap); | ||
1481 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); | ||
1482 | return 1; | ||
1483 | } | ||
1484 | #endif | ||
1485 | return 0; /* irq not handled */ | ||
1486 | } | ||
1487 | |||
1488 | static unsigned int __ata_sff_port_intr(struct ata_port *ap, | ||
1489 | struct ata_queued_cmd *qc, | ||
1490 | bool hsmv_on_idle) | ||
1491 | { | ||
1492 | u8 status; | ||
1493 | 1493 | ||
1494 | VPRINTK("ata%u: protocol %d task_state %d\n", | 1494 | VPRINTK("ata%u: protocol %d task_state %d\n", |
1495 | ap->print_id, qc->tf.protocol, ap->hsm_task_state); | 1495 | ap->print_id, qc->tf.protocol, ap->hsm_task_state); |
@@ -1506,47 +1506,24 @@ unsigned int ata_sff_host_intr(struct ata_port *ap, | |||
1506 | * need to check ata_is_atapi(qc->tf.protocol) again. | 1506 | * need to check ata_is_atapi(qc->tf.protocol) again. |
1507 | */ | 1507 | */ |
1508 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) | 1508 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) |
1509 | goto idle_irq; | 1509 | return ata_sff_idle_irq(ap); |
1510 | break; | ||
1511 | case HSM_ST_LAST: | ||
1512 | if (qc->tf.protocol == ATA_PROT_DMA || | ||
1513 | qc->tf.protocol == ATAPI_PROT_DMA) { | ||
1514 | /* check status of DMA engine */ | ||
1515 | host_stat = ap->ops->bmdma_status(ap); | ||
1516 | VPRINTK("ata%u: host_stat 0x%X\n", | ||
1517 | ap->print_id, host_stat); | ||
1518 | |||
1519 | /* if it's not our irq... */ | ||
1520 | if (!(host_stat & ATA_DMA_INTR)) | ||
1521 | goto idle_irq; | ||
1522 | |||
1523 | /* before we do anything else, clear DMA-Start bit */ | ||
1524 | ap->ops->bmdma_stop(qc); | ||
1525 | bmdma_stopped = true; | ||
1526 | |||
1527 | if (unlikely(host_stat & ATA_DMA_ERR)) { | ||
1528 | /* error when transfering data to/from memory */ | ||
1529 | qc->err_mask |= AC_ERR_HOST_BUS; | ||
1530 | ap->hsm_task_state = HSM_ST_ERR; | ||
1531 | } | ||
1532 | } | ||
1533 | break; | 1510 | break; |
1534 | case HSM_ST: | 1511 | case HSM_ST: |
1512 | case HSM_ST_LAST: | ||
1535 | break; | 1513 | break; |
1536 | default: | 1514 | default: |
1537 | goto idle_irq; | 1515 | return ata_sff_idle_irq(ap); |
1538 | } | 1516 | } |
1539 | 1517 | ||
1540 | |||
1541 | /* check main status, clearing INTRQ if needed */ | 1518 | /* check main status, clearing INTRQ if needed */ |
1542 | status = ata_sff_irq_status(ap); | 1519 | status = ata_sff_irq_status(ap); |
1543 | if (status & ATA_BUSY) { | 1520 | if (status & ATA_BUSY) { |
1544 | if (bmdma_stopped) { | 1521 | if (hsmv_on_idle) { |
1545 | /* BMDMA engine is already stopped, we're screwed */ | 1522 | /* BMDMA engine is already stopped, we're screwed */ |
1546 | qc->err_mask |= AC_ERR_HSM; | 1523 | qc->err_mask |= AC_ERR_HSM; |
1547 | ap->hsm_task_state = HSM_ST_ERR; | 1524 | ap->hsm_task_state = HSM_ST_ERR; |
1548 | } else | 1525 | } else |
1549 | goto idle_irq; | 1526 | return ata_sff_idle_irq(ap); |
1550 | } | 1527 | } |
1551 | 1528 | ||
1552 | /* clear irq events */ | 1529 | /* clear irq events */ |
@@ -1555,43 +1532,30 @@ unsigned int ata_sff_host_intr(struct ata_port *ap, | |||
1555 | 1532 | ||
1556 | ata_sff_hsm_move(ap, qc, status, 0); | 1533 | ata_sff_hsm_move(ap, qc, status, 0); |
1557 | 1534 | ||
1558 | if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || | ||
1559 | qc->tf.protocol == ATAPI_PROT_DMA)) | ||
1560 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
1561 | |||
1562 | return 1; /* irq handled */ | 1535 | return 1; /* irq handled */ |
1563 | |||
1564 | idle_irq: | ||
1565 | ap->stats.idle_irq++; | ||
1566 | |||
1567 | #ifdef ATA_IRQ_TRAP | ||
1568 | if ((ap->stats.idle_irq % 1000) == 0) { | ||
1569 | ap->ops->sff_check_status(ap); | ||
1570 | if (ap->ops->sff_irq_clear) | ||
1571 | ap->ops->sff_irq_clear(ap); | ||
1572 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); | ||
1573 | return 1; | ||
1574 | } | ||
1575 | #endif | ||
1576 | return 0; /* irq not handled */ | ||
1577 | } | 1536 | } |
1578 | EXPORT_SYMBOL_GPL(ata_sff_host_intr); | ||
1579 | 1537 | ||
1580 | /** | 1538 | /** |
1581 | * ata_sff_interrupt - Default ATA host interrupt handler | 1539 | * ata_sff_port_intr - Handle SFF port interrupt |
1582 | * @irq: irq line (unused) | 1540 | * @ap: Port on which interrupt arrived (possibly...) |
1583 | * @dev_instance: pointer to our ata_host information structure | 1541 | * @qc: Taskfile currently active in engine |
1584 | * | 1542 | * |
1585 | * Default interrupt handler for PCI IDE devices. Calls | 1543 | * Handle port interrupt for given queued command. |
1586 | * ata_sff_host_intr() for each port that is not disabled. | ||
1587 | * | 1544 | * |
1588 | * LOCKING: | 1545 | * LOCKING: |
1589 | * Obtains host lock during operation. | 1546 | * spin_lock_irqsave(host lock) |
1590 | * | 1547 | * |
1591 | * RETURNS: | 1548 | * RETURNS: |
1592 | * IRQ_NONE or IRQ_HANDLED. | 1549 | * One if interrupt was handled, zero if not (shared irq). |
1593 | */ | 1550 | */ |
1594 | irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) | 1551 | unsigned int ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) |
1552 | { | ||
1553 | return __ata_sff_port_intr(ap, qc, false); | ||
1554 | } | ||
1555 | EXPORT_SYMBOL_GPL(ata_sff_port_intr); | ||
1556 | |||
1557 | static inline irqreturn_t __ata_sff_interrupt(int irq, void *dev_instance, | ||
1558 | unsigned int (*port_intr)(struct ata_port *, struct ata_queued_cmd *)) | ||
1595 | { | 1559 | { |
1596 | struct ata_host *host = dev_instance; | 1560 | struct ata_host *host = dev_instance; |
1597 | bool retried = false; | 1561 | bool retried = false; |
@@ -1611,7 +1575,7 @@ retry: | |||
1611 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 1575 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
1612 | if (qc) { | 1576 | if (qc) { |
1613 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) | 1577 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) |
1614 | handled |= ata_sff_host_intr(ap, qc); | 1578 | handled |= port_intr(ap, qc); |
1615 | else | 1579 | else |
1616 | polling |= 1 << i; | 1580 | polling |= 1 << i; |
1617 | } else | 1581 | } else |
@@ -1661,6 +1625,25 @@ retry: | |||
1661 | 1625 | ||
1662 | return IRQ_RETVAL(handled); | 1626 | return IRQ_RETVAL(handled); |
1663 | } | 1627 | } |
1628 | |||
1629 | /** | ||
1630 | * ata_sff_interrupt - Default SFF ATA host interrupt handler | ||
1631 | * @irq: irq line (unused) | ||
1632 | * @dev_instance: pointer to our ata_host information structure | ||
1633 | * | ||
1634 | * Default interrupt handler for PCI IDE devices. Calls | ||
1635 | * ata_sff_port_intr() for each port that is not disabled. | ||
1636 | * | ||
1637 | * LOCKING: | ||
1638 | * Obtains host lock during operation. | ||
1639 | * | ||
1640 | * RETURNS: | ||
1641 | * IRQ_NONE or IRQ_HANDLED. | ||
1642 | */ | ||
1643 | irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) | ||
1644 | { | ||
1645 | return __ata_sff_interrupt(irq, dev_instance, ata_sff_port_intr); | ||
1646 | } | ||
1664 | EXPORT_SYMBOL_GPL(ata_sff_interrupt); | 1647 | EXPORT_SYMBOL_GPL(ata_sff_interrupt); |
1665 | 1648 | ||
1666 | /** | 1649 | /** |
@@ -1698,7 +1681,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap) | |||
1698 | status); | 1681 | status); |
1699 | /* Run the host interrupt logic as if the interrupt had not been | 1682 | /* Run the host interrupt logic as if the interrupt had not been |
1700 | lost */ | 1683 | lost */ |
1701 | ata_sff_host_intr(ap, qc); | 1684 | ata_sff_port_intr(ap, qc); |
1702 | } | 1685 | } |
1703 | EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); | 1686 | EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); |
1704 | 1687 | ||
@@ -2541,7 +2524,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev, | |||
2541 | host->flags |= hflag; | 2524 | host->flags |= hflag; |
2542 | 2525 | ||
2543 | pci_set_master(pdev); | 2526 | pci_set_master(pdev); |
2544 | rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); | 2527 | rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); |
2545 | out: | 2528 | out: |
2546 | if (rc == 0) | 2529 | if (rc == 0) |
2547 | devres_remove_group(&pdev->dev, NULL); | 2530 | devres_remove_group(&pdev->dev, NULL); |
@@ -2788,6 +2771,75 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc) | |||
2788 | EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue); | 2771 | EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue); |
2789 | 2772 | ||
2790 | /** | 2773 | /** |
2774 | * ata_bmdma_port_intr - Handle BMDMA port interrupt | ||
2775 | * @ap: Port on which interrupt arrived (possibly...) | ||
2776 | * @qc: Taskfile currently active in engine | ||
2777 | * | ||
2778 | * Handle port interrupt for given queued command. | ||
2779 | * | ||
2780 | * LOCKING: | ||
2781 | * spin_lock_irqsave(host lock) | ||
2782 | * | ||
2783 | * RETURNS: | ||
2784 | * One if interrupt was handled, zero if not (shared irq). | ||
2785 | */ | ||
2786 | unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) | ||
2787 | { | ||
2788 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
2789 | u8 host_stat = 0; | ||
2790 | bool bmdma_stopped = false; | ||
2791 | unsigned int handled; | ||
2792 | |||
2793 | if (ap->hsm_task_state == HSM_ST_LAST && ata_is_dma(qc->tf.protocol)) { | ||
2794 | /* check status of DMA engine */ | ||
2795 | host_stat = ap->ops->bmdma_status(ap); | ||
2796 | VPRINTK("ata%u: host_stat 0x%X\n", ap->print_id, host_stat); | ||
2797 | |||
2798 | /* if it's not our irq... */ | ||
2799 | if (!(host_stat & ATA_DMA_INTR)) | ||
2800 | return ata_sff_idle_irq(ap); | ||
2801 | |||
2802 | /* before we do anything else, clear DMA-Start bit */ | ||
2803 | ap->ops->bmdma_stop(qc); | ||
2804 | bmdma_stopped = true; | ||
2805 | |||
2806 | if (unlikely(host_stat & ATA_DMA_ERR)) { | ||
2807 | /* error when transfering data to/from memory */ | ||
2808 | qc->err_mask |= AC_ERR_HOST_BUS; | ||
2809 | ap->hsm_task_state = HSM_ST_ERR; | ||
2810 | } | ||
2811 | } | ||
2812 | |||
2813 | handled = __ata_sff_port_intr(ap, qc, bmdma_stopped); | ||
2814 | |||
2815 | if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) | ||
2816 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
2817 | |||
2818 | return handled; | ||
2819 | } | ||
2820 | EXPORT_SYMBOL_GPL(ata_bmdma_port_intr); | ||
2821 | |||
2822 | /** | ||
2823 | * ata_bmdma_interrupt - Default BMDMA ATA host interrupt handler | ||
2824 | * @irq: irq line (unused) | ||
2825 | * @dev_instance: pointer to our ata_host information structure | ||
2826 | * | ||
2827 | * Default interrupt handler for PCI IDE devices. Calls | ||
2828 | * ata_bmdma_port_intr() for each port that is not disabled. | ||
2829 | * | ||
2830 | * LOCKING: | ||
2831 | * Obtains host lock during operation. | ||
2832 | * | ||
2833 | * RETURNS: | ||
2834 | * IRQ_NONE or IRQ_HANDLED. | ||
2835 | */ | ||
2836 | irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance) | ||
2837 | { | ||
2838 | return __ata_sff_interrupt(irq, dev_instance, ata_bmdma_port_intr); | ||
2839 | } | ||
2840 | EXPORT_SYMBOL_GPL(ata_bmdma_interrupt); | ||
2841 | |||
2842 | /** | ||
2791 | * ata_bmdma_error_handler - Stock error handler for BMDMA controller | 2843 | * ata_bmdma_error_handler - Stock error handler for BMDMA controller |
2792 | * @ap: port to handle error for | 2844 | * @ap: port to handle error for |
2793 | * | 2845 | * |