summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a
diff options
context:
space:
mode:
authorKonsta Holtta <kholtta@nvidia.com>2018-11-13 08:36:19 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2019-02-05 12:04:20 -0500
commit3794afbeb177ed0932d166d30bb2af9d9859dff9 (patch)
treeddec116ed6ebee65f14108aaa54b84e3869589d4 /drivers/gpu/nvgpu/gk20a
parented6e3960903b9e2ba82ded06d1abfe3dec0ac865 (diff)
gpu: nvgpu: add safe channel id lookup
Add gk20a_channel_from_id() to retrieve a channel, given a raw channel ID, with a reference taken (or NULL if the channel was dead). This makes it harder to mistakenly use a channel that's dead and thus uncovers bugs sooner. Convert code to use the new lookup when applicable; work remains to convert complex uses where a ref should have been taken but hasn't. The channel ID is also validated against FIFO_INVAL_CHANNEL_ID; NULL is returned for such IDs. This is often useful and does not hurt when unnecessary. However, this does not prevent the case where a channel would be closed and reopened again when someone would hold a stale channel number. In all such conditions the caller should hold a reference already. The only conditions where a channel can be safely looked up by an id and used without taking a ref are when initializing or deinitializing the list of channels. Jira NVGPU-1460 Change-Id: I0a30968d17c1e0784d315a676bbe69c03a73481c Signed-off-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1955400 Signed-off-by: Debarshi Dutta <ddutta@nvidia.com> (cherry picked from commit 7df3d587502c2de997dfbe8ea8ddc114d0a0481e in dev-kernel) Reviewed-on: https://git-master.nvidia.com/r/2008515 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c18
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c7
2 files changed, 13 insertions, 12 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index 9691d51b..f4a4591d 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -1172,7 +1172,7 @@ gk20a_refch_from_inst_ptr(struct gk20a *g, u64 inst_ptr)
1172 struct channel_gk20a *ch; 1172 struct channel_gk20a *ch;
1173 u64 ch_inst_ptr; 1173 u64 ch_inst_ptr;
1174 1174
1175 ch = gk20a_channel_get(&f->channel[ci]); 1175 ch = gk20a_channel_from_id(g, ci);
1176 /* only alive channels are searched */ 1176 /* only alive channels are searched */
1177 if (!ch) { 1177 if (!ch) {
1178 continue; 1178 continue;
@@ -1959,9 +1959,9 @@ void gk20a_fifo_recover_ch(struct gk20a *g, u32 chid, bool verbose, int rc_type)
1959 gk20a_fifo_recover(g, engines, chid, false, true, verbose, 1959 gk20a_fifo_recover(g, engines, chid, false, true, verbose,
1960 rc_type); 1960 rc_type);
1961 } else { 1961 } else {
1962 struct channel_gk20a *ch = &g->fifo.channel[chid]; 1962 struct channel_gk20a *ch = gk20a_channel_from_id(g, chid);
1963 1963
1964 if (gk20a_channel_get(ch)) { 1964 if (ch != NULL) {
1965 gk20a_channel_abort(ch, false); 1965 gk20a_channel_abort(ch, false);
1966 1966
1967 if (gk20a_fifo_error_ch(g, ch)) { 1967 if (gk20a_fifo_error_ch(g, ch)) {
@@ -2710,9 +2710,9 @@ static void gk20a_fifo_pbdma_fault_rc(struct gk20a *g,
2710 id = fifo_pbdma_status_id_v(status); 2710 id = fifo_pbdma_status_id_v(status);
2711 if (fifo_pbdma_status_id_type_v(status) 2711 if (fifo_pbdma_status_id_type_v(status)
2712 == fifo_pbdma_status_id_type_chid_v()) { 2712 == fifo_pbdma_status_id_type_chid_v()) {
2713 struct channel_gk20a *ch = &f->channel[id]; 2713 struct channel_gk20a *ch = gk20a_channel_from_id(g, id);
2714 2714
2715 if (gk20a_channel_get(ch)) { 2715 if (ch != NULL) {
2716 g->ops.fifo.set_error_notifier(ch, error_notifier); 2716 g->ops.fifo.set_error_notifier(ch, error_notifier);
2717 gk20a_fifo_recover_ch(g, id, true, RC_TYPE_PBDMA_FAULT); 2717 gk20a_fifo_recover_ch(g, id, true, RC_TYPE_PBDMA_FAULT);
2718 gk20a_channel_put(ch); 2718 gk20a_channel_put(ch);
@@ -2924,12 +2924,12 @@ void gk20a_fifo_preempt_timeout_rc(struct gk20a *g, u32 id,
2924 gk20a_fifo_recover_tsg(g, id, true, 2924 gk20a_fifo_recover_tsg(g, id, true,
2925 RC_TYPE_PREEMPT_TIMEOUT); 2925 RC_TYPE_PREEMPT_TIMEOUT);
2926 } else { 2926 } else {
2927 struct channel_gk20a *ch = &g->fifo.channel[id]; 2927 struct channel_gk20a *ch = gk20a_channel_from_id(g, id);
2928 2928
2929 nvgpu_err(g, 2929 nvgpu_err(g,
2930 "preempt channel %d timeout", id); 2930 "preempt channel %d timeout", id);
2931 2931
2932 if (gk20a_channel_get(ch)) { 2932 if (ch != NULL) {
2933 g->ops.fifo.set_error_notifier(ch, 2933 g->ops.fifo.set_error_notifier(ch,
2934 NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT); 2934 NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT);
2935 gk20a_fifo_recover_ch(g, id, true, 2935 gk20a_fifo_recover_ch(g, id, true,
@@ -4031,8 +4031,8 @@ void gk20a_debug_dump_all_channel_status_ramfc(struct gk20a *g,
4031 } 4031 }
4032 4032
4033 for (chid = 0; chid < f->num_channels; chid++) { 4033 for (chid = 0; chid < f->num_channels; chid++) {
4034 struct channel_gk20a *ch = &f->channel[chid]; 4034 struct channel_gk20a *ch = gk20a_channel_from_id(g, chid);
4035 if (gk20a_channel_get(ch)) { 4035 if (ch != NULL) {
4036 ch_state[chid] = 4036 ch_state[chid] =
4037 nvgpu_kmalloc(g, sizeof(struct ch_state) + 4037 nvgpu_kmalloc(g, sizeof(struct ch_state) +
4038 ram_in_alloc_size_v()); 4038 ram_in_alloc_size_v());
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index 8cb66279..928d80cb 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -5581,15 +5581,16 @@ static struct channel_gk20a *gk20a_gr_get_channel_from_ctx(
5581 if (gr->chid_tlb[i].curr_ctx == curr_ctx) { 5581 if (gr->chid_tlb[i].curr_ctx == curr_ctx) {
5582 chid = gr->chid_tlb[i].chid; 5582 chid = gr->chid_tlb[i].chid;
5583 tsgid = gr->chid_tlb[i].tsgid; 5583 tsgid = gr->chid_tlb[i].tsgid;
5584 ret = gk20a_channel_get(&f->channel[chid]); 5584 ret = gk20a_channel_from_id(g, chid);
5585 goto unlock; 5585 goto unlock;
5586 } 5586 }
5587 } 5587 }
5588 5588
5589 /* slow path */ 5589 /* slow path */
5590 for (chid = 0; chid < f->num_channels; chid++) { 5590 for (chid = 0; chid < f->num_channels; chid++) {
5591 struct channel_gk20a *ch = &f->channel[chid]; 5591 struct channel_gk20a *ch = gk20a_channel_from_id(g, chid);
5592 if (gk20a_channel_get(ch) == NULL) { 5592
5593 if (ch == NULL) {
5593 continue; 5594 continue;
5594 } 5595 }
5595 5596