diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/fifo_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 4f3363f2..ad7162fc 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -1561,6 +1561,54 @@ static u32 fifo_error_isr(struct gk20a *g, u32 fifo_intr) | |||
1561 | return handled; | 1561 | return handled; |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | static inline void gk20a_fifo_reset_pbdma_header(struct gk20a *g, int pbdma_id) | ||
1565 | { | ||
1566 | gk20a_writel(g, pbdma_pb_header_r(pbdma_id), | ||
1567 | pbdma_pb_header_first_true_f() | | ||
1568 | pbdma_pb_header_type_non_inc_f()); | ||
1569 | } | ||
1570 | |||
1571 | static inline void gk20a_fifo_reset_pbdma_method(struct gk20a *g, int pbdma_id, | ||
1572 | int pbdma_method_index) | ||
1573 | { | ||
1574 | u32 pbdma_method_stride; | ||
1575 | u32 pbdma_method_reg; | ||
1576 | |||
1577 | pbdma_method_stride = pbdma_method1_r(pbdma_id) - | ||
1578 | pbdma_method0_r(pbdma_id); | ||
1579 | |||
1580 | pbdma_method_reg = pbdma_method0_r(pbdma_id) + | ||
1581 | (pbdma_method_index * pbdma_method_stride); | ||
1582 | |||
1583 | gk20a_writel(g, pbdma_method_reg, | ||
1584 | pbdma_method0_valid_true_f() | | ||
1585 | pbdma_method0_first_true_f() | | ||
1586 | pbdma_method0_addr_f( | ||
1587 | pbdma_udma_nop_r() >> 2)); | ||
1588 | } | ||
1589 | |||
1590 | static bool gk20a_fifo_is_sw_method_subch(struct gk20a *g, int pbdma_id, | ||
1591 | int pbdma_method_index) | ||
1592 | { | ||
1593 | u32 pbdma_method_stride; | ||
1594 | u32 pbdma_method_reg, pbdma_method_subch; | ||
1595 | |||
1596 | pbdma_method_stride = pbdma_method1_r(pbdma_id) - | ||
1597 | pbdma_method0_r(pbdma_id); | ||
1598 | |||
1599 | pbdma_method_reg = pbdma_method0_r(pbdma_id) + | ||
1600 | (pbdma_method_index * pbdma_method_stride); | ||
1601 | |||
1602 | pbdma_method_subch = pbdma_method0_subch_v( | ||
1603 | gk20a_readl(g, pbdma_method_reg)); | ||
1604 | |||
1605 | if (pbdma_method_subch == 5 || pbdma_method_subch == 6 || | ||
1606 | pbdma_method_subch == 7) | ||
1607 | return true; | ||
1608 | |||
1609 | return false; | ||
1610 | } | ||
1611 | |||
1564 | static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | 1612 | static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, |
1565 | struct gk20a *g, | 1613 | struct gk20a *g, |
1566 | struct fifo_gk20a *f, | 1614 | struct fifo_gk20a *f, |
@@ -1570,6 +1618,7 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | |||
1570 | u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id)); | 1618 | u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id)); |
1571 | u32 handled = 0; | 1619 | u32 handled = 0; |
1572 | bool reset = false; | 1620 | bool reset = false; |
1621 | int i; | ||
1573 | 1622 | ||
1574 | gk20a_dbg_fn(""); | 1623 | gk20a_dbg_fn(""); |
1575 | 1624 | ||
@@ -1580,11 +1629,15 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | |||
1580 | f->intr.pbdma.channel_fatal_0 | | 1629 | f->intr.pbdma.channel_fatal_0 | |
1581 | f->intr.pbdma.restartable_0) & pbdma_intr_0) { | 1630 | f->intr.pbdma.restartable_0) & pbdma_intr_0) { |
1582 | gk20a_err(dev_from_gk20a(g), | 1631 | gk20a_err(dev_from_gk20a(g), |
1583 | "pbdma_intr_0(%d):0x%08x PBH: %08x SHADOW: %08x M0: %08x", | 1632 | "pbdma_intr_0(%d):0x%08x PBH: %08x SHADOW: %08x M0: %08x %08x %08x %08x", |
1584 | pbdma_id, pbdma_intr_0, | 1633 | pbdma_id, pbdma_intr_0, |
1585 | gk20a_readl(g, pbdma_pb_header_r(pbdma_id)), | 1634 | gk20a_readl(g, pbdma_pb_header_r(pbdma_id)), |
1586 | gk20a_readl(g, pbdma_hdr_shadow_r(pbdma_id)), | 1635 | gk20a_readl(g, pbdma_hdr_shadow_r(pbdma_id)), |
1587 | gk20a_readl(g, pbdma_method0_r(pbdma_id))); | 1636 | gk20a_readl(g, pbdma_method0_r(pbdma_id)), |
1637 | gk20a_readl(g, pbdma_method1_r(pbdma_id)), | ||
1638 | gk20a_readl(g, pbdma_method2_r(pbdma_id)), | ||
1639 | gk20a_readl(g, pbdma_method3_r(pbdma_id)) | ||
1640 | ); | ||
1588 | reset = true; | 1641 | reset = true; |
1589 | handled |= ((f->intr.pbdma.device_fatal_0 | | 1642 | handled |= ((f->intr.pbdma.device_fatal_0 | |
1590 | f->intr.pbdma.channel_fatal_0 | | 1643 | f->intr.pbdma.channel_fatal_0 | |
@@ -1592,7 +1645,29 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | |||
1592 | pbdma_intr_0); | 1645 | pbdma_intr_0); |
1593 | } | 1646 | } |
1594 | 1647 | ||
1595 | gk20a_writel(g, pbdma_method0_r(pbdma_id), 0); | 1648 | if (pbdma_intr_0 & pbdma_intr_0_pbentry_pending_f()) { |
1649 | gk20a_fifo_reset_pbdma_header(g, pbdma_id); | ||
1650 | gk20a_fifo_reset_pbdma_method(g, pbdma_id, 0); | ||
1651 | reset = true; | ||
1652 | } | ||
1653 | |||
1654 | if (pbdma_intr_0 & pbdma_intr_0_method_pending_f()) { | ||
1655 | gk20a_fifo_reset_pbdma_method(g, pbdma_id, 0); | ||
1656 | reset = true; | ||
1657 | } | ||
1658 | |||
1659 | if (pbdma_intr_0 & pbdma_intr_0_device_pending_f()) { | ||
1660 | gk20a_fifo_reset_pbdma_header(g, pbdma_id); | ||
1661 | |||
1662 | for (i = 0; i < 4; i++) { | ||
1663 | if (gk20a_fifo_is_sw_method_subch(g, | ||
1664 | pbdma_id, i)) | ||
1665 | gk20a_fifo_reset_pbdma_method(g, | ||
1666 | pbdma_id, i); | ||
1667 | } | ||
1668 | reset = true; | ||
1669 | } | ||
1670 | |||
1596 | gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0); | 1671 | gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0); |
1597 | } | 1672 | } |
1598 | 1673 | ||