diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 93 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h | 8 |
3 files changed, 79 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 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index bed8a361..04d22abb 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | |||
@@ -146,6 +146,7 @@ void gk20a_fifo_isr(struct gk20a *g); | |||
146 | void gk20a_fifo_nonstall_isr(struct gk20a *g); | 146 | void gk20a_fifo_nonstall_isr(struct gk20a *g); |
147 | 147 | ||
148 | int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid); | 148 | int gk20a_fifo_preempt_channel(struct gk20a *g, u32 hw_chid); |
149 | int gk20a_fifo_preempt_tsg(struct gk20a *g, u32 tsgid); | ||
149 | 150 | ||
150 | int gk20a_fifo_enable_engine_activity(struct gk20a *g, | 151 | int gk20a_fifo_enable_engine_activity(struct gk20a *g, |
151 | struct fifo_engine_info_gk20a *eng_info); | 152 | struct fifo_engine_info_gk20a *eng_info); |
diff --git a/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h index 83e7d776..aa77d026 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_fifo_gk20a.h | |||
@@ -398,10 +398,18 @@ static inline u32 fifo_preempt_type_channel_f(void) | |||
398 | { | 398 | { |
399 | return 0x0; | 399 | return 0x0; |
400 | } | 400 | } |
401 | static inline u32 fifo_preempt_type_tsg_f(void) | ||
402 | { | ||
403 | return 0x1000000; | ||
404 | } | ||
401 | static inline u32 fifo_preempt_chid_f(u32 v) | 405 | static inline u32 fifo_preempt_chid_f(u32 v) |
402 | { | 406 | { |
403 | return (v & 0xfff) << 0; | 407 | return (v & 0xfff) << 0; |
404 | } | 408 | } |
409 | static inline u32 fifo_preempt_id_f(u32 v) | ||
410 | { | ||
411 | return (v & 0xfff) << 0; | ||
412 | } | ||
405 | static inline u32 fifo_trigger_mmu_fault_r(u32 i) | 413 | static inline u32 fifo_trigger_mmu_fault_r(u32 i) |
406 | { | 414 | { |
407 | return 0x00002a30 + i*4; | 415 | return 0x00002a30 + i*4; |