diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 21 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.h | 13 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 170 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 14 |
6 files changed, 110 insertions, 118 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 6de264f4..b9cba434 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -900,12 +900,6 @@ static int gk20a_pm_finalize_poweron(struct device *dev) | |||
900 | goto done; | 900 | goto done; |
901 | } | 901 | } |
902 | 902 | ||
903 | err = gk20a_init_pmu_setup_hw2(g); | ||
904 | if (err) { | ||
905 | gk20a_err(dev, "failed to init gk20a pmu_hw2"); | ||
906 | goto done; | ||
907 | } | ||
908 | |||
909 | err = gk20a_init_therm_support(g); | 903 | err = gk20a_init_therm_support(g); |
910 | if (err) { | 904 | if (err) { |
911 | gk20a_err(dev, "failed to init gk20a therm"); | 905 | gk20a_err(dev, "failed to init gk20a therm"); |
@@ -1471,6 +1465,8 @@ static int gk20a_probe(struct platform_device *dev) | |||
1471 | cfb_add_device(&dev->dev); | 1465 | cfb_add_device(&dev->dev); |
1472 | #endif | 1466 | #endif |
1473 | 1467 | ||
1468 | gk20a_init_gr(gk20a); | ||
1469 | |||
1474 | return 0; | 1470 | return 0; |
1475 | } | 1471 | } |
1476 | 1472 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 3d70afd5..b23bb540 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -3534,7 +3534,7 @@ clean_up: | |||
3534 | return ret; | 3534 | return ret; |
3535 | } | 3535 | } |
3536 | 3536 | ||
3537 | static void gr_gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) | 3537 | void gr_gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) |
3538 | { | 3538 | { |
3539 | struct fifo_gk20a *f = &g->fifo; | 3539 | struct fifo_gk20a *f = &g->fifo; |
3540 | struct fifo_engine_info_gk20a *gr_info = | 3540 | struct fifo_engine_info_gk20a *gr_info = |
@@ -4569,9 +4569,19 @@ int gk20a_init_gr_support(struct gk20a *g) | |||
4569 | if (err) | 4569 | if (err) |
4570 | return err; | 4570 | return err; |
4571 | 4571 | ||
4572 | /* GR is inialized, signal possible waiters */ | ||
4573 | g->gr.initialized = true; | ||
4574 | wake_up(&g->gr.init_wq); | ||
4575 | |||
4572 | return 0; | 4576 | return 0; |
4573 | } | 4577 | } |
4574 | 4578 | ||
4579 | /* Wait until GR is initialized */ | ||
4580 | void gk20a_gr_wait_initialized(struct gk20a *g) | ||
4581 | { | ||
4582 | wait_event(g->gr.init_wq, g->gr.initialized); | ||
4583 | } | ||
4584 | |||
4575 | #define NVA297_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dc | 4585 | #define NVA297_SET_ALPHA_CIRCULAR_BUFFER_SIZE 0x02dc |
4576 | #define NVA297_SET_CIRCULAR_BUFFER_SIZE 0x1280 | 4586 | #define NVA297_SET_CIRCULAR_BUFFER_SIZE 0x1280 |
4577 | #define NVA297_SET_SHADER_EXCEPTIONS 0x1528 | 4587 | #define NVA297_SET_SHADER_EXCEPTIONS 0x1528 |
@@ -5550,6 +5560,8 @@ int gk20a_gr_suspend(struct gk20a *g) | |||
5550 | 5560 | ||
5551 | gk20a_gr_flush_channel_tlb(&g->gr); | 5561 | gk20a_gr_flush_channel_tlb(&g->gr); |
5552 | 5562 | ||
5563 | g->gr.initialized = false; | ||
5564 | |||
5553 | gk20a_dbg_fn("done"); | 5565 | gk20a_dbg_fn("done"); |
5554 | return ret; | 5566 | return ret; |
5555 | } | 5567 | } |
@@ -6816,7 +6828,12 @@ void gr_gk20a_commit_global_pagepool(struct gk20a *g, | |||
6816 | gr_pd_pagepool_valid_true_f(), patch); | 6828 | gr_pd_pagepool_valid_true_f(), patch); |
6817 | } | 6829 | } |
6818 | 6830 | ||
6819 | void gk20a_init_gr(struct gpu_ops *gops) | 6831 | void gk20a_init_gr(struct gk20a *g) |
6832 | { | ||
6833 | init_waitqueue_head(&g->gr.init_wq); | ||
6834 | } | ||
6835 | |||
6836 | void gk20a_init_gr_ops(struct gpu_ops *gops) | ||
6820 | { | 6837 | { |
6821 | gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg; | 6838 | gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg; |
6822 | gops->gr.bundle_cb_defaults = gr_gk20a_bundle_cb_defaults; | 6839 | gops->gr.bundle_cb_defaults = gr_gk20a_bundle_cb_defaults; |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 9e0883d6..05c27ffd 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h | |||
@@ -204,7 +204,9 @@ struct gr_gk20a { | |||
204 | #define GR_NETLIST_STATIC_A 'A' | 204 | #define GR_NETLIST_STATIC_A 'A' |
205 | int netlist; | 205 | int netlist; |
206 | 206 | ||
207 | wait_queue_head_t init_wq; | ||
207 | int initialized; | 208 | int initialized; |
209 | |||
208 | u32 num_fbps; | 210 | u32 num_fbps; |
209 | 211 | ||
210 | u32 comptags_per_cacheline; | 212 | u32 comptags_per_cacheline; |
@@ -313,9 +315,11 @@ struct gk20a_ctxsw_bootloader_desc { | |||
313 | }; | 315 | }; |
314 | 316 | ||
315 | struct gpu_ops; | 317 | struct gpu_ops; |
316 | void gk20a_init_gr(struct gpu_ops *gops); | 318 | void gk20a_init_gr(struct gk20a *g); |
319 | void gk20a_init_gr_ops(struct gpu_ops *gops); | ||
317 | int gk20a_init_gr_support(struct gk20a *g); | 320 | int gk20a_init_gr_support(struct gk20a *g); |
318 | int gk20a_gr_reset(struct gk20a *g); | 321 | int gk20a_gr_reset(struct gk20a *g); |
322 | void gk20a_gr_wait_initialized(struct gk20a *g); | ||
319 | 323 | ||
320 | int gk20a_init_gr_channel(struct channel_gk20a *ch_gk20a); | 324 | int gk20a_init_gr_channel(struct channel_gk20a *ch_gk20a); |
321 | 325 | ||
@@ -356,14 +360,17 @@ int gr_gk20a_fecs_set_reglist_virtual_addr(struct gk20a *g, u64 pmu_va); | |||
356 | void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine); | 360 | void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine); |
357 | void gr_gk20a_init_blcg_mode(struct gk20a *g, u32 mode, u32 engine); | 361 | void gr_gk20a_init_blcg_mode(struct gk20a *g, u32 mode, u32 engine); |
358 | 362 | ||
363 | void gr_gk20a_pmu_save_zbc(struct gk20a *g, u32 entries); | ||
364 | |||
359 | /* sm */ | 365 | /* sm */ |
360 | bool gk20a_gr_sm_debugger_attached(struct gk20a *g); | 366 | bool gk20a_gr_sm_debugger_attached(struct gk20a *g); |
361 | 367 | ||
362 | #define gr_gk20a_elpg_protected_call(g, func) \ | 368 | #define gr_gk20a_elpg_protected_call(g, func) \ |
363 | ({ \ | 369 | ({ \ |
364 | int err; \ | 370 | int err = 0; \ |
365 | if (support_gk20a_pmu()) \ | 371 | if (support_gk20a_pmu()) \ |
366 | gk20a_pmu_disable_elpg(g); \ | 372 | err = gk20a_pmu_disable_elpg(g); \ |
373 | if (err) return err; \ | ||
367 | err = func; \ | 374 | err = func; \ |
368 | if (support_gk20a_pmu()) \ | 375 | if (support_gk20a_pmu()) \ |
369 | gk20a_pmu_enable_elpg(g); \ | 376 | gk20a_pmu_enable_elpg(g); \ |
diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index de6c3713..66bc47a9 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c | |||
@@ -43,7 +43,7 @@ int gk20a_init_hal(struct gpu_ops *gops) | |||
43 | { | 43 | { |
44 | *gops = gk20a_ops; | 44 | *gops = gk20a_ops; |
45 | gk20a_init_ltc(gops); | 45 | gk20a_init_ltc(gops); |
46 | gk20a_init_gr(gops); | 46 | gk20a_init_gr_ops(gops); |
47 | gk20a_init_fb(gops); | 47 | gk20a_init_fb(gops); |
48 | gk20a_init_fifo(gops); | 48 | gk20a_init_fifo(gops); |
49 | gk20a_init_gr_ctx(gops); | 49 | gk20a_init_gr_ctx(gops); |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index bccd4100..b784b9a6 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | 29 | ||
30 | #include "gk20a.h" | 30 | #include "gk20a.h" |
31 | #include "gr_gk20a.h" | ||
31 | #include "hw_mc_gk20a.h" | 32 | #include "hw_mc_gk20a.h" |
32 | #include "hw_pwr_gk20a.h" | 33 | #include "hw_pwr_gk20a.h" |
33 | #include "hw_top_gk20a.h" | 34 | #include "hw_top_gk20a.h" |
@@ -40,8 +41,7 @@ | |||
40 | static void pmu_dump_falcon_stats(struct pmu_gk20a *pmu); | 41 | static void pmu_dump_falcon_stats(struct pmu_gk20a *pmu); |
41 | static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, | 42 | static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, |
42 | u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt); | 43 | u32 *ingating_time, u32 *ungating_time, u32 *gating_cnt); |
43 | static void gk20a_init_pmu_setup_hw2_workqueue(struct work_struct *work); | 44 | static void pmu_setup_hw(struct work_struct *work); |
44 | static void pmu_save_zbc(struct gk20a *g, u32 entries); | ||
45 | static void ap_callback_init_and_enable_ctrl( | 45 | static void ap_callback_init_and_enable_ctrl( |
46 | struct gk20a *g, struct pmu_msg *msg, | 46 | struct gk20a *g, struct pmu_msg *msg, |
47 | void *param, u32 seq_desc, u32 status); | 47 | void *param, u32 seq_desc, u32 status); |
@@ -1582,8 +1582,7 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) | |||
1582 | pmu->ucode_image = (u32 *)((u8 *)pmu->desc + | 1582 | pmu->ucode_image = (u32 *)((u8 *)pmu->desc + |
1583 | pmu->desc->descriptor_size); | 1583 | pmu->desc->descriptor_size); |
1584 | 1584 | ||
1585 | 1585 | INIT_WORK(&pmu->pg_init, pmu_setup_hw); | |
1586 | INIT_WORK(&pmu->pg_init, gk20a_init_pmu_setup_hw2_workqueue); | ||
1587 | 1586 | ||
1588 | dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); | 1587 | dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); |
1589 | pmu->ucode.cpuva = dma_alloc_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, | 1588 | pmu->ucode.cpuva = dma_alloc_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, |
@@ -1607,7 +1606,6 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) | |||
1607 | } | 1606 | } |
1608 | 1607 | ||
1609 | pmu->seq_buf.iova = iova; | 1608 | pmu->seq_buf.iova = iova; |
1610 | init_waitqueue_head(&pmu->pg_wq); | ||
1611 | 1609 | ||
1612 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, | 1610 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, |
1613 | pmu->ucode.cpuva, | 1611 | pmu->ucode.cpuva, |
@@ -1668,6 +1666,8 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) | |||
1668 | gk20a_free_sgtable(&sgt_pmu_ucode); | 1666 | gk20a_free_sgtable(&sgt_pmu_ucode); |
1669 | gk20a_free_sgtable(&sgt_seq_buf); | 1667 | gk20a_free_sgtable(&sgt_seq_buf); |
1670 | 1668 | ||
1669 | pmu->sw_ready = true; | ||
1670 | |||
1671 | skip_init: | 1671 | skip_init: |
1672 | mutex_init(&pmu->elpg_mutex); | 1672 | mutex_init(&pmu->elpg_mutex); |
1673 | mutex_init(&pmu->isr_mutex); | 1673 | mutex_init(&pmu->isr_mutex); |
@@ -1741,7 +1741,7 @@ static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg, | |||
1741 | } | 1741 | } |
1742 | 1742 | ||
1743 | pmu->buf_loaded = (eng_buf_stat->status == PMU_PG_MSG_ENG_BUF_LOADED); | 1743 | pmu->buf_loaded = (eng_buf_stat->status == PMU_PG_MSG_ENG_BUF_LOADED); |
1744 | wake_up(&pmu->pg_wq); | 1744 | schedule_work(&pmu->pg_init); |
1745 | } | 1745 | } |
1746 | 1746 | ||
1747 | int gk20a_init_pmu_setup_hw1(struct gk20a *g) | 1747 | int gk20a_init_pmu_setup_hw1(struct gk20a *g) |
@@ -1781,15 +1781,37 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g) | |||
1781 | static int gk20a_aelpg_init(struct gk20a *g); | 1781 | static int gk20a_aelpg_init(struct gk20a *g); |
1782 | static int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id); | 1782 | static int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id); |
1783 | 1783 | ||
1784 | static void pmu_setup_hw_load_zbc(struct gk20a *g); | ||
1785 | static void pmu_setup_hw_enable_elpg(struct gk20a *g); | ||
1784 | 1786 | ||
1785 | static void gk20a_init_pmu_setup_hw2_workqueue(struct work_struct *work) | 1787 | static void pmu_setup_hw(struct work_struct *work) |
1786 | { | 1788 | { |
1787 | struct pmu_gk20a *pmu = container_of(work, struct pmu_gk20a, pg_init); | 1789 | struct pmu_gk20a *pmu = container_of(work, struct pmu_gk20a, pg_init); |
1788 | struct gk20a *g = pmu->g; | 1790 | struct gk20a *g = pmu->g; |
1789 | gk20a_init_pmu_setup_hw2(g); | 1791 | |
1792 | switch (pmu->pmu_state) { | ||
1793 | case PMU_STATE_ELPG_BOOTED: | ||
1794 | gk20a_dbg_pmu("elpg booted"); | ||
1795 | gk20a_init_pmu_bind_fecs(g); | ||
1796 | break; | ||
1797 | case PMU_STATE_LOADING_PG_BUF: | ||
1798 | gk20a_dbg_pmu("loaded pg buf"); | ||
1799 | pmu_setup_hw_load_zbc(g); | ||
1800 | break; | ||
1801 | case PMU_STATE_LOADING_ZBC: | ||
1802 | gk20a_dbg_pmu("loaded zbc"); | ||
1803 | pmu_setup_hw_enable_elpg(g); | ||
1804 | break; | ||
1805 | case PMU_STATE_STARTED: | ||
1806 | gk20a_dbg_pmu("PMU booted"); | ||
1807 | break; | ||
1808 | default: | ||
1809 | gk20a_dbg_pmu("invalid state"); | ||
1810 | break; | ||
1811 | } | ||
1790 | } | 1812 | } |
1791 | 1813 | ||
1792 | int gk20a_init_pmu_setup_hw2(struct gk20a *g) | 1814 | int gk20a_init_pmu_bind_fecs(struct gk20a *g) |
1793 | { | 1815 | { |
1794 | struct pmu_gk20a *pmu = &g->pmu; | 1816 | struct pmu_gk20a *pmu = &g->pmu; |
1795 | struct mm_gk20a *mm = &g->mm; | 1817 | struct mm_gk20a *mm = &g->mm; |
@@ -1797,19 +1819,15 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1797 | struct device *d = dev_from_gk20a(g); | 1819 | struct device *d = dev_from_gk20a(g); |
1798 | struct pmu_cmd cmd; | 1820 | struct pmu_cmd cmd; |
1799 | u32 desc; | 1821 | u32 desc; |
1800 | long remain; | ||
1801 | int err; | 1822 | int err; |
1802 | bool status; | ||
1803 | u32 size; | 1823 | u32 size; |
1804 | struct sg_table *sgt_pg_buf; | 1824 | struct sg_table *sgt_pg_buf; |
1805 | dma_addr_t iova; | 1825 | dma_addr_t iova; |
1806 | 1826 | ||
1807 | gk20a_dbg_fn(""); | 1827 | gk20a_dbg_fn(""); |
1808 | 1828 | ||
1809 | if (!support_gk20a_pmu()) | ||
1810 | return 0; | ||
1811 | |||
1812 | size = 0; | 1829 | size = 0; |
1830 | gk20a_gr_wait_initialized(g); | ||
1813 | err = gr_gk20a_fecs_get_reglist_img_size(g, &size); | 1831 | err = gr_gk20a_fecs_get_reglist_img_size(g, &size); |
1814 | if (err) { | 1832 | if (err) { |
1815 | gk20a_err(dev_from_gk20a(g), | 1833 | gk20a_err(dev_from_gk20a(g), |
@@ -1817,14 +1835,13 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1817 | return err; | 1835 | return err; |
1818 | } | 1836 | } |
1819 | 1837 | ||
1820 | if (!pmu->sw_ready) { | 1838 | if (!pmu->pg_buf.cpuva) { |
1821 | pmu->pg_buf.cpuva = dma_alloc_coherent(d, size, | 1839 | pmu->pg_buf.cpuva = dma_alloc_coherent(d, size, |
1822 | &iova, | 1840 | &iova, |
1823 | GFP_KERNEL); | 1841 | GFP_KERNEL); |
1824 | if (!pmu->pg_buf.cpuva) { | 1842 | if (!pmu->pg_buf.cpuva) { |
1825 | gk20a_err(d, "failed to allocate memory\n"); | 1843 | gk20a_err(d, "failed to allocate memory\n"); |
1826 | err = -ENOMEM; | 1844 | return -ENOMEM; |
1827 | goto err; | ||
1828 | } | 1845 | } |
1829 | 1846 | ||
1830 | pmu->pg_buf.iova = iova; | 1847 | pmu->pg_buf.iova = iova; |
@@ -1853,30 +1870,6 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1853 | gk20a_free_sgtable(&sgt_pg_buf); | 1870 | gk20a_free_sgtable(&sgt_pg_buf); |
1854 | } | 1871 | } |
1855 | 1872 | ||
1856 | /* | ||
1857 | * This is the actual point at which sw setup is complete, so set the | ||
1858 | * sw_ready flag here. | ||
1859 | */ | ||
1860 | pmu->sw_ready = true; | ||
1861 | |||
1862 | /* TBD: acquire pmu hw mutex */ | ||
1863 | |||
1864 | /* TBD: post reset again? */ | ||
1865 | |||
1866 | /* PMU_INIT message handler will send PG_INIT */ | ||
1867 | remain = wait_event_timeout( | ||
1868 | pmu->pg_wq, | ||
1869 | (status = (pmu->elpg_ready && | ||
1870 | pmu->stat_dmem_offset != 0 && | ||
1871 | pmu->elpg_stat == PMU_ELPG_STAT_OFF)), | ||
1872 | msecs_to_jiffies(gk20a_get_gr_idle_timeout(g))); | ||
1873 | if (status == 0) { | ||
1874 | gk20a_err(dev_from_gk20a(g), | ||
1875 | "PG_INIT_ACK failed, remaining timeout : 0x%lx", remain); | ||
1876 | pmu_dump_falcon_stats(pmu); | ||
1877 | return -EBUSY; | ||
1878 | } | ||
1879 | |||
1880 | err = gr_gk20a_fecs_set_reglist_bind_inst(g, mm->pmu.inst_block.cpu_pa); | 1873 | err = gr_gk20a_fecs_set_reglist_bind_inst(g, mm->pmu.inst_block.cpu_pa); |
1881 | if (err) { | 1874 | if (err) { |
1882 | gk20a_err(dev_from_gk20a(g), | 1875 | gk20a_err(dev_from_gk20a(g), |
@@ -1906,17 +1899,24 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1906 | gk20a_dbg_pmu("cmd post PMU_PG_CMD_ID_ENG_BUF_LOAD PMU_PGENG_GR_BUFFER_IDX_FECS"); | 1899 | gk20a_dbg_pmu("cmd post PMU_PG_CMD_ID_ENG_BUF_LOAD PMU_PGENG_GR_BUFFER_IDX_FECS"); |
1907 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ, | 1900 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ, |
1908 | pmu_handle_pg_buf_config_msg, pmu, &desc, ~0); | 1901 | pmu_handle_pg_buf_config_msg, pmu, &desc, ~0); |
1902 | pmu->pmu_state = PMU_STATE_LOADING_PG_BUF; | ||
1903 | return err; | ||
1909 | 1904 | ||
1910 | remain = wait_event_timeout( | 1905 | err_free_sgtable: |
1911 | pmu->pg_wq, | 1906 | gk20a_free_sgtable(&sgt_pg_buf); |
1912 | pmu->buf_loaded, | 1907 | err_free_pg_buf: |
1913 | msecs_to_jiffies(gk20a_get_gr_idle_timeout(g))); | 1908 | dma_free_coherent(d, size, |
1914 | if (!pmu->buf_loaded) { | 1909 | pmu->pg_buf.cpuva, pmu->pg_buf.iova); |
1915 | gk20a_err(dev_from_gk20a(g), | 1910 | pmu->pg_buf.cpuva = NULL; |
1916 | "PGENG FECS buffer load failed, remaining timeout : 0x%lx", | 1911 | pmu->pg_buf.iova = 0; |
1917 | remain); | 1912 | return err; |
1918 | return -EBUSY; | 1913 | } |
1919 | } | 1914 | |
1915 | static void pmu_setup_hw_load_zbc(struct gk20a *g) | ||
1916 | { | ||
1917 | struct pmu_gk20a *pmu = &g->pmu; | ||
1918 | struct pmu_cmd cmd; | ||
1919 | u32 desc; | ||
1920 | 1920 | ||
1921 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 1921 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
1922 | cmd.hdr.unit_id = PMU_UNIT_PG; | 1922 | cmd.hdr.unit_id = PMU_UNIT_PG; |
@@ -1933,17 +1933,12 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1933 | gk20a_dbg_pmu("cmd post PMU_PG_CMD_ID_ENG_BUF_LOAD PMU_PGENG_GR_BUFFER_IDX_ZBC"); | 1933 | gk20a_dbg_pmu("cmd post PMU_PG_CMD_ID_ENG_BUF_LOAD PMU_PGENG_GR_BUFFER_IDX_ZBC"); |
1934 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ, | 1934 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_LPQ, |
1935 | pmu_handle_pg_buf_config_msg, pmu, &desc, ~0); | 1935 | pmu_handle_pg_buf_config_msg, pmu, &desc, ~0); |
1936 | pmu->pmu_state = PMU_STATE_LOADING_ZBC; | ||
1937 | } | ||
1936 | 1938 | ||
1937 | remain = wait_event_timeout( | 1939 | static void pmu_setup_hw_enable_elpg(struct gk20a *g) |
1938 | pmu->pg_wq, | 1940 | { |
1939 | pmu->buf_loaded, | 1941 | struct pmu_gk20a *pmu = &g->pmu; |
1940 | msecs_to_jiffies(gk20a_get_gr_idle_timeout(g))); | ||
1941 | if (!pmu->buf_loaded) { | ||
1942 | gk20a_err(dev_from_gk20a(g), | ||
1943 | "PGENG ZBC buffer load failed, remaining timeout 0x%lx", | ||
1944 | remain); | ||
1945 | return -EBUSY; | ||
1946 | } | ||
1947 | 1942 | ||
1948 | /* | 1943 | /* |
1949 | * FIXME: To enable ELPG, we increase the PMU ext2priv timeout unit to | 1944 | * FIXME: To enable ELPG, we increase the PMU ext2priv timeout unit to |
@@ -1954,17 +1949,11 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1954 | gk20a_writel(g, 0x10a164, 0x109ff); | 1949 | gk20a_writel(g, 0x10a164, 0x109ff); |
1955 | 1950 | ||
1956 | pmu->initialized = true; | 1951 | pmu->initialized = true; |
1957 | 1952 | pmu->pmu_state = PMU_STATE_STARTED; | |
1958 | /* | ||
1959 | * We can't guarantee that gr code to enable ELPG will be | ||
1960 | * invoked, so we explicitly call disable-enable here | ||
1961 | * to enable elpg. | ||
1962 | */ | ||
1963 | gk20a_pmu_disable_elpg(g); | ||
1964 | 1953 | ||
1965 | pmu->zbc_ready = true; | 1954 | pmu->zbc_ready = true; |
1966 | /* Save zbc table after PMU is initialized. */ | 1955 | /* Save zbc table after PMU is initialized. */ |
1967 | pmu_save_zbc(g, 0xf); | 1956 | gr_gk20a_pmu_save_zbc(g, 0xf); |
1968 | 1957 | ||
1969 | if (g->elpg_enabled) | 1958 | if (g->elpg_enabled) |
1970 | gk20a_pmu_enable_elpg(g); | 1959 | gk20a_pmu_enable_elpg(g); |
@@ -1976,18 +1965,6 @@ int gk20a_init_pmu_setup_hw2(struct gk20a *g) | |||
1976 | gk20a_aelpg_init(g); | 1965 | gk20a_aelpg_init(g); |
1977 | gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS); | 1966 | gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS); |
1978 | } | 1967 | } |
1979 | |||
1980 | return 0; | ||
1981 | |||
1982 | err_free_sgtable: | ||
1983 | gk20a_free_sgtable(&sgt_pg_buf); | ||
1984 | err_free_pg_buf: | ||
1985 | dma_free_coherent(d, size, | ||
1986 | pmu->pg_buf.cpuva, pmu->pg_buf.iova); | ||
1987 | pmu->pg_buf.cpuva = NULL; | ||
1988 | pmu->pg_buf.iova = 0; | ||
1989 | err: | ||
1990 | return err; | ||
1991 | } | 1968 | } |
1992 | 1969 | ||
1993 | int gk20a_init_pmu_support(struct gk20a *g) | 1970 | int gk20a_init_pmu_support(struct gk20a *g) |
@@ -2036,18 +2013,17 @@ static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg, | |||
2036 | switch (elpg_msg->msg) { | 2013 | switch (elpg_msg->msg) { |
2037 | case PMU_PG_ELPG_MSG_INIT_ACK: | 2014 | case PMU_PG_ELPG_MSG_INIT_ACK: |
2038 | gk20a_dbg_pmu("INIT_PG is acknowledged from PMU"); | 2015 | gk20a_dbg_pmu("INIT_PG is acknowledged from PMU"); |
2039 | pmu->elpg_ready = true; | ||
2040 | wake_up(&pmu->pg_wq); | ||
2041 | break; | 2016 | break; |
2042 | case PMU_PG_ELPG_MSG_ALLOW_ACK: | 2017 | case PMU_PG_ELPG_MSG_ALLOW_ACK: |
2043 | gk20a_dbg_pmu("ALLOW is acknowledged from PMU"); | 2018 | gk20a_dbg_pmu("ALLOW is acknowledged from PMU"); |
2044 | pmu->elpg_stat = PMU_ELPG_STAT_ON; | 2019 | pmu->elpg_stat = PMU_ELPG_STAT_ON; |
2045 | wake_up(&pmu->pg_wq); | ||
2046 | break; | 2020 | break; |
2047 | case PMU_PG_ELPG_MSG_DISALLOW_ACK: | 2021 | case PMU_PG_ELPG_MSG_DISALLOW_ACK: |
2048 | gk20a_dbg_pmu("DISALLOW is acknowledged from PMU"); | 2022 | gk20a_dbg_pmu("DISALLOW is acknowledged from PMU"); |
2049 | pmu->elpg_stat = PMU_ELPG_STAT_OFF; | 2023 | pmu->elpg_stat = PMU_ELPG_STAT_OFF; |
2050 | wake_up(&pmu->pg_wq); | 2024 | if (pmu->pmu_state == PMU_STATE_STARTING) |
2025 | pmu->pmu_state = PMU_STATE_ELPG_BOOTED; | ||
2026 | schedule_work(&pmu->pg_init); | ||
2051 | break; | 2027 | break; |
2052 | default: | 2028 | default: |
2053 | gk20a_err(dev_from_gk20a(g), | 2029 | gk20a_err(dev_from_gk20a(g), |
@@ -2074,7 +2050,6 @@ static void pmu_handle_pg_stat_msg(struct gk20a *g, struct pmu_msg *msg, | |||
2074 | case PMU_PG_STAT_MSG_RESP_DMEM_OFFSET: | 2050 | case PMU_PG_STAT_MSG_RESP_DMEM_OFFSET: |
2075 | gk20a_dbg_pmu("ALLOC_DMEM_OFFSET is acknowledged from PMU"); | 2051 | gk20a_dbg_pmu("ALLOC_DMEM_OFFSET is acknowledged from PMU"); |
2076 | pmu->stat_dmem_offset = msg->msg.pg.stat.data; | 2052 | pmu->stat_dmem_offset = msg->msg.pg.stat.data; |
2077 | wake_up(&pmu->pg_wq); | ||
2078 | break; | 2053 | break; |
2079 | default: | 2054 | default: |
2080 | break; | 2055 | break; |
@@ -2131,7 +2106,7 @@ static int pmu_init_powergating(struct pmu_gk20a *pmu) | |||
2131 | 2106 | ||
2132 | /* disallow ELPG initially | 2107 | /* disallow ELPG initially |
2133 | PMU ucode requires a disallow cmd before allow cmd */ | 2108 | PMU ucode requires a disallow cmd before allow cmd */ |
2134 | pmu->elpg_stat = PMU_ELPG_STAT_ON; /* set for wait_event PMU_ELPG_STAT_OFF */ | 2109 | pmu->elpg_stat = PMU_ELPG_STAT_OFF; /* set for wait_event PMU_ELPG_STAT_OFF */ |
2135 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 2110 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
2136 | cmd.hdr.unit_id = PMU_UNIT_PG; | 2111 | cmd.hdr.unit_id = PMU_UNIT_PG; |
2137 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); | 2112 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); |
@@ -2144,7 +2119,9 @@ static int pmu_init_powergating(struct pmu_gk20a *pmu) | |||
2144 | pmu_handle_pg_elpg_msg, pmu, &seq, ~0); | 2119 | pmu_handle_pg_elpg_msg, pmu, &seq, ~0); |
2145 | 2120 | ||
2146 | /* start with elpg disabled until first enable call */ | 2121 | /* start with elpg disabled until first enable call */ |
2147 | pmu->elpg_refcnt = 1; | 2122 | pmu->elpg_refcnt = 0; |
2123 | |||
2124 | pmu->pmu_state = PMU_STATE_STARTING; | ||
2148 | 2125 | ||
2149 | return 0; | 2126 | return 0; |
2150 | } | 2127 | } |
@@ -2482,7 +2459,7 @@ static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, | |||
2482 | pmu->zbc_save_done = 1; | 2459 | pmu->zbc_save_done = 1; |
2483 | } | 2460 | } |
2484 | 2461 | ||
2485 | static void pmu_save_zbc(struct gk20a *g, u32 entries) | 2462 | void gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) |
2486 | { | 2463 | { |
2487 | struct pmu_gk20a *pmu = &g->pmu; | 2464 | struct pmu_gk20a *pmu = &g->pmu; |
2488 | struct pmu_cmd cmd; | 2465 | struct pmu_cmd cmd; |
@@ -2508,12 +2485,6 @@ static void pmu_save_zbc(struct gk20a *g, u32 entries) | |||
2508 | gk20a_err(dev_from_gk20a(g), "ZBC save timeout"); | 2485 | gk20a_err(dev_from_gk20a(g), "ZBC save timeout"); |
2509 | } | 2486 | } |
2510 | 2487 | ||
2511 | void gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) | ||
2512 | { | ||
2513 | if (g->pmu.zbc_ready) | ||
2514 | pmu_save_zbc(g, entries); | ||
2515 | } | ||
2516 | |||
2517 | static int pmu_perfmon_start_sampling(struct pmu_gk20a *pmu) | 2488 | static int pmu_perfmon_start_sampling(struct pmu_gk20a *pmu) |
2518 | { | 2489 | { |
2519 | struct gk20a *g = pmu->g; | 2490 | struct gk20a *g = pmu->g; |
@@ -3195,9 +3166,6 @@ int gk20a_pmu_enable_elpg(struct gk20a *g) | |||
3195 | 3166 | ||
3196 | gk20a_dbg_fn(""); | 3167 | gk20a_dbg_fn(""); |
3197 | 3168 | ||
3198 | if (!pmu->elpg_ready || !pmu->initialized) | ||
3199 | goto exit; | ||
3200 | |||
3201 | mutex_lock(&pmu->elpg_mutex); | 3169 | mutex_lock(&pmu->elpg_mutex); |
3202 | 3170 | ||
3203 | pmu->elpg_refcnt++; | 3171 | pmu->elpg_refcnt++; |
@@ -3225,7 +3193,6 @@ int gk20a_pmu_enable_elpg(struct gk20a *g) | |||
3225 | 3193 | ||
3226 | exit_unlock: | 3194 | exit_unlock: |
3227 | mutex_unlock(&pmu->elpg_mutex); | 3195 | mutex_unlock(&pmu->elpg_mutex); |
3228 | exit: | ||
3229 | gk20a_dbg_fn("done"); | 3196 | gk20a_dbg_fn("done"); |
3230 | return ret; | 3197 | return ret; |
3231 | } | 3198 | } |
@@ -3239,9 +3206,6 @@ int gk20a_pmu_disable_elpg(struct gk20a *g) | |||
3239 | 3206 | ||
3240 | gk20a_dbg_fn(""); | 3207 | gk20a_dbg_fn(""); |
3241 | 3208 | ||
3242 | if (!pmu->elpg_ready || !pmu->initialized) | ||
3243 | return 0; | ||
3244 | |||
3245 | mutex_lock(&pmu->elpg_mutex); | 3209 | mutex_lock(&pmu->elpg_mutex); |
3246 | 3210 | ||
3247 | pmu->elpg_refcnt--; | 3211 | pmu->elpg_refcnt--; |
@@ -3353,10 +3317,10 @@ int gk20a_pmu_destroy(struct gk20a *g) | |||
3353 | g->pg_gating_cnt += gating_cnt; | 3317 | g->pg_gating_cnt += gating_cnt; |
3354 | 3318 | ||
3355 | pmu_enable(pmu, false); | 3319 | pmu_enable(pmu, false); |
3320 | pmu->pmu_state = PMU_STATE_OFF; | ||
3356 | pmu->pmu_ready = false; | 3321 | pmu->pmu_ready = false; |
3357 | pmu->perfmon_ready = false; | 3322 | pmu->perfmon_ready = false; |
3358 | pmu->zbc_ready = false; | 3323 | pmu->zbc_ready = false; |
3359 | pmu->elpg_ready = false; | ||
3360 | 3324 | ||
3361 | gk20a_dbg_fn("done"); | 3325 | gk20a_dbg_fn("done"); |
3362 | return 0; | 3326 | return 0; |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 8aaea33f..2843d483 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -987,6 +987,14 @@ struct pmu_pg_stats { | |||
987 | #define PMU_FALCON_REG_RSVD2 (31) | 987 | #define PMU_FALCON_REG_RSVD2 (31) |
988 | #define PMU_FALCON_REG_SIZE (32) | 988 | #define PMU_FALCON_REG_SIZE (32) |
989 | 989 | ||
990 | /* Choices for pmu_state */ | ||
991 | #define PMU_STATE_OFF 0 /* PMU is off */ | ||
992 | #define PMU_STATE_STARTING 1 /* PMU is booting */ | ||
993 | #define PMU_STATE_ELPG_BOOTED 2 /* ELPG is initialized */ | ||
994 | #define PMU_STATE_LOADING_PG_BUF 3 /* Loading PG buf */ | ||
995 | #define PMU_STATE_LOADING_ZBC 4 /* Loading ZBC buf */ | ||
996 | #define PMU_STATE_STARTED 5 /* Fully unitialized */ | ||
997 | |||
990 | struct pmu_gk20a { | 998 | struct pmu_gk20a { |
991 | 999 | ||
992 | struct gk20a *g; | 1000 | struct gk20a *g; |
@@ -1022,9 +1030,9 @@ struct pmu_gk20a { | |||
1022 | 1030 | ||
1023 | u32 stat_dmem_offset; | 1031 | u32 stat_dmem_offset; |
1024 | 1032 | ||
1025 | bool elpg_ready; | ||
1026 | u32 elpg_stat; | 1033 | u32 elpg_stat; |
1027 | wait_queue_head_t pg_wq; | 1034 | |
1035 | int pmu_state; | ||
1028 | 1036 | ||
1029 | #define PMU_ELPG_ENABLE_ALLOW_DELAY_MSEC 1 /* msec */ | 1037 | #define PMU_ELPG_ENABLE_ALLOW_DELAY_MSEC 1 /* msec */ |
1030 | struct work_struct pg_init; | 1038 | struct work_struct pg_init; |
@@ -1053,7 +1061,7 @@ struct pmu_gk20a { | |||
1053 | }; | 1061 | }; |
1054 | 1062 | ||
1055 | int gk20a_init_pmu_support(struct gk20a *g); | 1063 | int gk20a_init_pmu_support(struct gk20a *g); |
1056 | int gk20a_init_pmu_setup_hw2(struct gk20a *g); | 1064 | int gk20a_init_pmu_bind_fecs(struct gk20a *g); |
1057 | 1065 | ||
1058 | void gk20a_pmu_isr(struct gk20a *g); | 1066 | void gk20a_pmu_isr(struct gk20a *g); |
1059 | 1067 | ||