From b6466fbe07d28fcc1a2ea93715a1f88b48dd8550 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Mon, 16 Jun 2014 12:08:18 +0530 Subject: gpu: nvgpu: add TSG support to runlists - when a TSG channel is made runnable, add it to TSG's runnable list - when a TSG channel is removed from runlist, remove it from TSG's runnable list When we rewrite the entire runlist : - first add all the channels which are not part of any TSG - then find all active TSGs, add an entry in runlist for the TSG (with TSG id and length of TSG) - then write entries for each channel in that TSG Bug 1470692 Change-Id: Ic55a4d5959abc72cd20b8224eb4c31d3ff411861 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/416612 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 76 ++++++++++++++++++++++++++++++++++-- drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 1 + drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 4 +- 3 files changed, 76 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index e9febb77..52c0627d 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -205,6 +205,7 @@ void gk20a_remove_fifo_support(struct fifo_gk20a *f) } kfree(runlist->active_channels); + kfree(runlist->active_tsgs); kfree(f->runlist_info); kfree(f->pbdma_map); @@ -316,6 +317,12 @@ static int init_runlist(struct gk20a *g, struct fifo_gk20a *f) if (!runlist->active_channels) goto clean_up_runlist_info; + runlist->active_tsgs = + kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), + GFP_KERNEL); + if (!runlist->active_tsgs) + goto clean_up_runlist_info; + runlist_size = ram_rl_entry_size_v() * f->num_channels; for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) { dma_addr_t iova; @@ -1734,8 +1741,11 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, u32 *runlist_entry = NULL; phys_addr_t runlist_pa; u32 old_buf, new_buf; - u32 chid; + u32 chid, tsgid; + struct channel_gk20a *ch; + struct tsg_gk20a *tsg; u32 count = 0; + int num_ch; runlist = &f->runlist_info[runlist_id]; /* valid channel, add/remove it from active list. @@ -1745,10 +1755,28 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, if (test_and_set_bit(hw_chid, runlist->active_channels) == 1) return 0; + if (gk20a_is_channel_marked_as_tsg( + &f->channel[hw_chid])) { + num_ch = gk20a_bind_runnable_channel_to_tsg( + &f->channel[hw_chid], + f->channel[hw_chid].tsgid); + if (num_ch > 0) + set_bit(f->channel[hw_chid].tsgid, + runlist->active_tsgs); + } } else { if (test_and_clear_bit(hw_chid, runlist->active_channels) == 0) return 0; + if (gk20a_is_channel_marked_as_tsg( + &f->channel[hw_chid])) { + num_ch = gk20a_unbind_channel_from_tsg( + &f->channel[hw_chid], + f->channel[hw_chid].tsgid); + if (!num_ch) + clear_bit(f->channel[hw_chid].tsgid, + runlist->active_tsgs); + } } } @@ -1773,14 +1801,56 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, if (hw_chid != ~0 || /* add/remove a valid channel */ add /* resume to add all channels back */) { runlist_entry = runlist_entry_base; + + /* add non-TSG channels first */ for_each_set_bit(chid, runlist->active_channels, f->num_channels) { - gk20a_dbg_info("add channel %d to runlist", chid); - runlist_entry[0] = chid; + ch = &f->channel[chid]; + + if (!gk20a_is_channel_marked_as_tsg(ch)) { + gk20a_dbg_info("add channel %d to runlist", + chid); + runlist_entry[0] = ram_rl_entry_chid_f(chid); + runlist_entry[1] = 0; + runlist_entry += 2; + count++; + } + } + + /* now add TSG entries and channels bound to TSG */ + mutex_lock(&f->tsg_inuse_mutex); + for_each_set_bit(tsgid, + runlist->active_tsgs, f->num_channels) { + tsg = &f->tsg[tsgid]; + /* add TSG entry */ + gk20a_dbg_info("add TSG %d to runlist", tsg->tsgid); + runlist_entry[0] = ram_rl_entry_id_f(tsg->tsgid) | + ram_rl_entry_type_f(ram_rl_entry_type_tsg_f()) | + ram_rl_entry_timeslice_scale_f( + ram_rl_entry_timeslice_scale_3_f()) | + ram_rl_entry_timeslice_timeout_f( + ram_rl_entry_timeslice_timeout_128_f()) | + ram_rl_entry_tsg_length_f( + tsg->num_runnable_channels); runlist_entry[1] = 0; runlist_entry += 2; count++; + + /* add channels bound to this TSG */ + mutex_lock(&tsg->ch_list_lock); + list_for_each_entry(ch, + &tsg->ch_runnable_list, ch_entry) { + gk20a_dbg_info("add channel %d to runlist", + ch->hw_chid); + runlist_entry[0] = + ram_rl_entry_chid_f(ch->hw_chid); + runlist_entry[1] = 0; + runlist_entry += 2; + count++; + } + mutex_unlock(&tsg->ch_list_lock); } + mutex_unlock(&f->tsg_inuse_mutex); } else /* suspend to remove all channels */ count = 0; diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index f94fce02..6e6907c1 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h @@ -30,6 +30,7 @@ struct fifo_runlist_info_gk20a { unsigned long *active_channels; + unsigned long *active_tsgs; /* Each engine has its own SW and HW runlist buffer.*/ struct runlist_mem_desc mem[MAX_RUNLIST_BUFFERS]; u32 cur_buffer; diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c index d9e10d30..7c65c695 100644 --- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c @@ -50,7 +50,7 @@ int gk20a_bind_runnable_channel_to_tsg(struct channel_gk20a *ch, int tsgid) tsg->num_runnable_channels += 1; mutex_unlock(&tsg->ch_list_lock); - return 0; + return tsg->num_runnable_channels; } int gk20a_unbind_channel_from_tsg(struct channel_gk20a *ch, int tsgid) @@ -68,7 +68,7 @@ int gk20a_unbind_channel_from_tsg(struct channel_gk20a *ch, int tsgid) tsg->num_runnable_channels -= 1; mutex_unlock(&tsg->ch_list_lock); - return 0; + return tsg->num_runnable_channels; } /* -- cgit v1.2.2