diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-01-12 08:21:37 -0500 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-02-05 11:07:10 -0500 |
commit | 8b665ac6b2984e07a290d5ecbcec2c93ec973c65 (patch) | |
tree | d830257de402437766711d7c0dddcb358dde1668 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |
parent | 2ca20e14ba1358b1ca32329bfb16a98de631642e (diff) |
gpu: nvgpu: move clean up of jobs to separate worker
We currently clean up the jobs in gk20a_channel_update()
which is called from nvhost worker thread
Instead of doing this, schedule another delayed worker thread
clean_up_work to clean up the jobs (with delay of 1 jiffies)
Keep update_gp_get() in channel_update() and not in
delayed worker since this will help in better book
keeping of gp_get
Also, this scheduling will help delay job clean-up so
that more number of jobs are batched for clean up
and hence less time is consumed by worker
Bug 1718092
Change-Id: If3b94b6aab93c92da4cf0d1c74aaba756f4cd838
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/931701
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 5e5bbcb0..1f63bbd8 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -64,6 +64,8 @@ static void gk20a_free_error_notifiers(struct channel_gk20a *ch); | |||
64 | 64 | ||
65 | static u32 gk20a_get_channel_watchdog_timeout(struct channel_gk20a *ch); | 65 | static u32 gk20a_get_channel_watchdog_timeout(struct channel_gk20a *ch); |
66 | 66 | ||
67 | static void gk20a_channel_clean_up_jobs(struct work_struct *work); | ||
68 | |||
67 | /* allocate GPU channel */ | 69 | /* allocate GPU channel */ |
68 | static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) | 70 | static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) |
69 | { | 71 | { |
@@ -1144,6 +1146,7 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | |||
1144 | ch->wdt_enabled = true; | 1146 | ch->wdt_enabled = true; |
1145 | ch->obj_class = 0; | 1147 | ch->obj_class = 0; |
1146 | ch->interleave = false; | 1148 | ch->interleave = false; |
1149 | ch->clean_up.scheduled = false; | ||
1147 | gk20a_fifo_set_channel_priority( | 1150 | gk20a_fifo_set_channel_priority( |
1148 | ch->g, 0, ch->hw_chid, ch->interleave); | 1151 | ch->g, 0, ch->hw_chid, ch->interleave); |
1149 | 1152 | ||
@@ -1771,6 +1774,32 @@ static int gk20a_free_priv_cmdbuf(struct channel_gk20a *c, | |||
1771 | return 0; | 1774 | return 0; |
1772 | } | 1775 | } |
1773 | 1776 | ||
1777 | static void gk20a_channel_schedule_job_clean_up(struct channel_gk20a *c) | ||
1778 | { | ||
1779 | mutex_lock(&c->clean_up.lock); | ||
1780 | |||
1781 | if (c->clean_up.scheduled) { | ||
1782 | mutex_unlock(&c->clean_up.lock); | ||
1783 | return; | ||
1784 | } | ||
1785 | |||
1786 | c->clean_up.scheduled = true; | ||
1787 | schedule_delayed_work(&c->clean_up.wq, 1); | ||
1788 | |||
1789 | mutex_unlock(&c->clean_up.lock); | ||
1790 | } | ||
1791 | |||
1792 | static void gk20a_channel_cancel_job_clean_up(struct channel_gk20a *c, | ||
1793 | bool wait_for_completion) | ||
1794 | { | ||
1795 | if (wait_for_completion) | ||
1796 | cancel_delayed_work_sync(&c->clean_up.wq); | ||
1797 | |||
1798 | mutex_lock(&c->clean_up.lock); | ||
1799 | c->clean_up.scheduled = false; | ||
1800 | mutex_unlock(&c->clean_up.lock); | ||
1801 | } | ||
1802 | |||
1774 | static int gk20a_channel_add_job(struct channel_gk20a *c, | 1803 | static int gk20a_channel_add_job(struct channel_gk20a *c, |
1775 | struct gk20a_fence *pre_fence, | 1804 | struct gk20a_fence *pre_fence, |
1776 | struct gk20a_fence *post_fence, | 1805 | struct gk20a_fence *post_fence, |
@@ -1832,22 +1861,28 @@ err_put_vm: | |||
1832 | return err; | 1861 | return err; |
1833 | } | 1862 | } |
1834 | 1863 | ||
1835 | void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) | 1864 | static void gk20a_channel_clean_up_jobs(struct work_struct *work) |
1836 | { | 1865 | { |
1837 | struct vm_gk20a *vm = c->vm; | 1866 | struct channel_gk20a *c = container_of(to_delayed_work(work), |
1867 | struct channel_gk20a, clean_up.wq); | ||
1868 | struct vm_gk20a *vm; | ||
1838 | struct channel_gk20a_job *job, *n; | 1869 | struct channel_gk20a_job *job, *n; |
1839 | struct gk20a_platform *platform = gk20a_get_platform(c->g->dev); | 1870 | struct gk20a_platform *platform; |
1840 | 1871 | ||
1841 | trace_gk20a_channel_update(c->hw_chid); | 1872 | c = gk20a_channel_get(c); |
1873 | if (!c) | ||
1874 | return; | ||
1842 | 1875 | ||
1843 | update_gp_get(c->g, c); | 1876 | vm = c->vm; |
1844 | wake_up(&c->submit_wq); | 1877 | platform = gk20a_get_platform(c->g->dev); |
1845 | 1878 | ||
1846 | mutex_lock(&c->submit_lock); | 1879 | mutex_lock(&c->submit_lock); |
1847 | 1880 | ||
1848 | /* gp_put check needs to be done inside submit lock */ | 1881 | /* gp_put check needs to be done inside submit lock */ |
1849 | check_gp_put(c->g, c); | 1882 | check_gp_put(c->g, c); |
1850 | 1883 | ||
1884 | gk20a_channel_cancel_job_clean_up(c, false); | ||
1885 | |||
1851 | mutex_lock(&c->jobs_lock); | 1886 | mutex_lock(&c->jobs_lock); |
1852 | list_for_each_entry_safe(job, n, &c->jobs, list) { | 1887 | list_for_each_entry_safe(job, n, &c->jobs, list) { |
1853 | struct gk20a *g = c->g; | 1888 | struct gk20a *g = c->g; |
@@ -1908,6 +1943,23 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) | |||
1908 | 1943 | ||
1909 | if (c->update_fn) | 1944 | if (c->update_fn) |
1910 | schedule_work(&c->update_fn_work); | 1945 | schedule_work(&c->update_fn_work); |
1946 | |||
1947 | gk20a_channel_put(c); | ||
1948 | } | ||
1949 | |||
1950 | void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) | ||
1951 | { | ||
1952 | c = gk20a_channel_get(c); | ||
1953 | if (!c) | ||
1954 | return; | ||
1955 | |||
1956 | update_gp_get(c->g, c); | ||
1957 | wake_up(&c->submit_wq); | ||
1958 | |||
1959 | trace_gk20a_channel_update(c->hw_chid); | ||
1960 | gk20a_channel_schedule_job_clean_up(c); | ||
1961 | |||
1962 | gk20a_channel_put(c); | ||
1911 | } | 1963 | } |
1912 | 1964 | ||
1913 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | 1965 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, |
@@ -2249,6 +2301,8 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) | |||
2249 | mutex_init(&c->timeout.lock); | 2301 | mutex_init(&c->timeout.lock); |
2250 | mutex_init(&c->sync_lock); | 2302 | mutex_init(&c->sync_lock); |
2251 | INIT_DELAYED_WORK(&c->timeout.wq, gk20a_channel_timeout_handler); | 2303 | INIT_DELAYED_WORK(&c->timeout.wq, gk20a_channel_timeout_handler); |
2304 | INIT_DELAYED_WORK(&c->clean_up.wq, gk20a_channel_clean_up_jobs); | ||
2305 | mutex_init(&c->clean_up.lock); | ||
2252 | INIT_LIST_HEAD(&c->jobs); | 2306 | INIT_LIST_HEAD(&c->jobs); |
2253 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 2307 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
2254 | mutex_init(&c->cyclestate.cyclestate_buffer_mutex); | 2308 | mutex_init(&c->cyclestate.cyclestate_buffer_mutex); |
@@ -2612,6 +2666,7 @@ int gk20a_channel_suspend(struct gk20a *g) | |||
2612 | if (ch->update_fn && | 2666 | if (ch->update_fn && |
2613 | work_pending(&ch->update_fn_work)) | 2667 | work_pending(&ch->update_fn_work)) |
2614 | flush_work(&ch->update_fn_work); | 2668 | flush_work(&ch->update_fn_work); |
2669 | gk20a_channel_cancel_job_clean_up(ch, true); | ||
2615 | 2670 | ||
2616 | channels_in_use = true; | 2671 | channels_in_use = true; |
2617 | 2672 | ||