diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/fifo_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 93 |
1 files changed, 70 insertions, 23 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 230e1722..56ff4c87 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -1512,29 +1512,22 @@ void gk20a_fifo_nonstall_isr(struct gk20a *g) | |||
1512 | return; | 1512 | return; |
1513 | } | 1513 | } |
1514 | 1514 | ||
1515 | int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid) | 1515 | static int __locked_fifo_preempt(struct gk20a *g, u32 id, bool is_tsg) |
1516 | { | 1516 | { |
1517 | struct fifo_gk20a *f = &g->fifo; | 1517 | u32 delay = GR_IDLE_CHECK_DEFAULT; |
1518 | unsigned long end_jiffies = jiffies | 1518 | unsigned long end_jiffies = jiffies |
1519 | + msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); | 1519 | + msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); |
1520 | u32 delay = GR_IDLE_CHECK_DEFAULT; | ||
1521 | u32 ret = 0; | 1520 | u32 ret = 0; |
1522 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; | ||
1523 | u32 mutex_ret = 0; | ||
1524 | u32 i; | ||
1525 | |||
1526 | gk20a_dbg_fn("%d", hw_chid); | ||
1527 | |||
1528 | /* we have no idea which runlist we are using. lock all */ | ||
1529 | for (i = 0; i < g->fifo.max_runlists; i++) | ||
1530 | mutex_lock(&f->runlist_info[i].mutex); | ||
1531 | |||
1532 | mutex_ret = pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | ||
1533 | 1521 | ||
1534 | /* issue preempt */ | 1522 | /* issue preempt */ |
1535 | gk20a_writel(g, fifo_preempt_r(), | 1523 | if (is_tsg) |
1536 | fifo_preempt_chid_f(hw_chid) | | 1524 | gk20a_writel(g, fifo_preempt_r(), |
1537 | fifo_preempt_type_channel_f()); | 1525 | fifo_preempt_id_f(id) | |
1526 | fifo_preempt_type_tsg_f()); | ||
1527 | else | ||
1528 | gk20a_writel(g, fifo_preempt_r(), | ||
1529 | fifo_preempt_chid_f(id) | | ||
1530 | fifo_preempt_type_channel_f()); | ||
1538 | 1531 | ||
1539 | /* wait for preempt */ | 1532 | /* wait for preempt */ |
1540 | ret = -EBUSY; | 1533 | ret = -EBUSY; |
@@ -1551,16 +1544,70 @@ int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid) | |||
1551 | !tegra_platform_is_silicon()); | 1544 | !tegra_platform_is_silicon()); |
1552 | 1545 | ||
1553 | if (ret) { | 1546 | if (ret) { |
1554 | struct channel_gk20a *ch = &g->fifo.channel[hw_chid]; | 1547 | if (is_tsg) { |
1548 | /* TODO: recovery for TSG */ | ||
1549 | gk20a_err(dev_from_gk20a(g), | ||
1550 | "preempt TSG %d timeout\n", id); | ||
1551 | } else { | ||
1552 | struct channel_gk20a *ch = &g->fifo.channel[id]; | ||
1555 | 1553 | ||
1556 | gk20a_err(dev_from_gk20a(g), "preempt channel %d timeout\n", | 1554 | gk20a_err(dev_from_gk20a(g), |
1557 | hw_chid); | 1555 | "preempt channel %d timeout\n", id); |
1558 | 1556 | ||
1559 | gk20a_set_error_notifier(ch, | 1557 | gk20a_set_error_notifier(ch, |
1560 | NVHOST_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); | 1558 | NVHOST_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); |
1561 | gk20a_fifo_recover_ch(g, hw_chid, true); | 1559 | gk20a_fifo_recover_ch(g, id, true); |
1560 | } | ||
1562 | } | 1561 | } |
1563 | 1562 | ||
1563 | return ret; | ||
1564 | } | ||
1565 | |||
1566 | int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid) | ||
1567 | { | ||
1568 | struct fifo_gk20a *f = &g->fifo; | ||
1569 | u32 ret = 0; | ||
1570 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; | ||
1571 | u32 mutex_ret = 0; | ||
1572 | u32 i; | ||
1573 | |||
1574 | gk20a_dbg_fn("%d", hw_chid); | ||
1575 | |||
1576 | /* we have no idea which runlist we are using. lock all */ | ||
1577 | for (i = 0; i < g->fifo.max_runlists; i++) | ||
1578 | mutex_lock(&f->runlist_info[i].mutex); | ||
1579 | |||
1580 | mutex_ret = pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | ||
1581 | |||
1582 | ret = __locked_fifo_preempt(g, hw_chid, false); | ||
1583 | |||
1584 | if (!mutex_ret) | ||
1585 | pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | ||
1586 | |||
1587 | for (i = 0; i < g->fifo.max_runlists; i++) | ||
1588 | mutex_unlock(&f->runlist_info[i].mutex); | ||
1589 | |||
1590 | return ret; | ||
1591 | } | ||
1592 | |||
1593 | int gk20a_fifo_preempt_tsg(struct gk20a *g, u32 tsgid) | ||
1594 | { | ||
1595 | struct fifo_gk20a *f = &g->fifo; | ||
1596 | u32 ret = 0; | ||
1597 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; | ||
1598 | u32 mutex_ret = 0; | ||
1599 | u32 i; | ||
1600 | |||
1601 | gk20a_dbg_fn("%d", tsgid); | ||
1602 | |||
1603 | /* we have no idea which runlist we are using. lock all */ | ||
1604 | for (i = 0; i < g->fifo.max_runlists; i++) | ||
1605 | mutex_lock(&f->runlist_info[i].mutex); | ||
1606 | |||
1607 | mutex_ret = pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | ||
1608 | |||
1609 | ret = __locked_fifo_preempt(g, tsgid, true); | ||
1610 | |||
1564 | if (!mutex_ret) | 1611 | if (!mutex_ret) |
1565 | pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | 1612 | pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); |
1566 | 1613 | ||