aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-sff.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-05-19 16:10:21 -0400
committerJeff Garzik <jgarzik@redhat.com>2010-05-25 19:40:24 -0400
commitc3b2889424c26f3b42962b6f39aabb4f1fd1b576 (patch)
treec131d260c18815cb84331357db75c17dabf083d8 /drivers/ata/libata-sff.c
parent37f65b8bc262a5ae4c8e58be92fe3032f0aaaf04 (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.c208
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}
1470EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); 1470EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
1471 1471
1472/** 1472static 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 */
1487unsigned 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
1488static 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
1564idle_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}
1578EXPORT_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 */
1594irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) 1551unsigned 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}
1555EXPORT_SYMBOL_GPL(ata_sff_port_intr);
1556
1557static 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 */
1643irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
1644{
1645 return __ata_sff_interrupt(irq, dev_instance, ata_sff_port_intr);
1646}
1664EXPORT_SYMBOL_GPL(ata_sff_interrupt); 1647EXPORT_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}
1703EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); 1686EXPORT_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);
2545out: 2528out:
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)
2788EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue); 2771EXPORT_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 */
2786unsigned 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}
2820EXPORT_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 */
2836irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance)
2837{
2838 return __ata_sff_interrupt(irq, dev_instance, ata_bmdma_port_intr);
2839}
2840EXPORT_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 *