diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2017-01-04 13:59:01 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-01-11 12:13:43 -0500 |
commit | 5e68c6e971d98fc9d4beaf69c5ca58f39f8db1a7 (patch) | |
tree | 6b67a949668f21858a27f0546068659ff680cc46 /drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |
parent | 318524ee2f8bc117db25608d432bcc60d92d8c08 (diff) |
gpu: nvgpu: add support for refcount tracking
If enabled, track actions (gets and puts) on channel reference counters.
Dump the most recent actions to syslog when
gk20a_wait_until_counter_is_N gets stuck when closing a channel.
GK20A_CHANNEL_REFCOUNT_TRACKING specifies the size of the action
history. Default is to disable completely, as this has some runtime
overhead.
Bug 1826754
Change-Id: I880b0efe8881044d02ae224c243a51cb6c2db8c1
Signed-off-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-on: http://git-master/r/1262424
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.h')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 697d1603..44a989da 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GK20A graphics channel | 2 | * GK20A graphics channel |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/semaphore.h> | 24 | #include <linux/semaphore.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/stacktrace.h> | ||
27 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
28 | #include <uapi/linux/nvgpu.h> | 29 | #include <uapi/linux/nvgpu.h> |
29 | 30 | ||
@@ -115,6 +116,40 @@ struct channel_gk20a_clean_up { | |||
115 | struct delayed_work wq; | 116 | struct delayed_work wq; |
116 | }; | 117 | }; |
117 | 118 | ||
119 | /* | ||
120 | * Track refcount actions, saving their stack traces. This number specifies how | ||
121 | * many most recent actions are stored in a buffer. Set to 0 to disable. 128 | ||
122 | * should be enough to track moderately hard problems from the start. | ||
123 | */ | ||
124 | #define GK20A_CHANNEL_REFCOUNT_TRACKING 0 | ||
125 | /* Stack depth for the saved actions. */ | ||
126 | #define GK20A_CHANNEL_REFCOUNT_TRACKING_STACKLEN 8 | ||
127 | |||
128 | /* | ||
129 | * Because the puts and gets are not linked together explicitly (although they | ||
130 | * should always come in pairs), it's not possible to tell which ref holder to | ||
131 | * delete from the list when doing a put. So, just store some number of most | ||
132 | * recent gets and puts in a ring buffer, to obtain a history. | ||
133 | * | ||
134 | * These are zeroed when a channel is closed, so a new one starts fresh. | ||
135 | */ | ||
136 | |||
137 | enum channel_gk20a_ref_action_type { | ||
138 | channel_gk20a_ref_action_get, | ||
139 | channel_gk20a_ref_action_put | ||
140 | }; | ||
141 | |||
142 | struct channel_gk20a_ref_action { | ||
143 | enum channel_gk20a_ref_action_type type; | ||
144 | unsigned long jiffies; | ||
145 | /* | ||
146 | * Many of these traces will be similar. Simpler to just capture | ||
147 | * duplicates than to have a separate database for the entries. | ||
148 | */ | ||
149 | struct stack_trace trace; | ||
150 | unsigned long trace_entries[GK20A_CHANNEL_REFCOUNT_TRACKING_STACKLEN]; | ||
151 | }; | ||
152 | |||
118 | /* this is the priv element of struct nvhost_channel */ | 153 | /* this is the priv element of struct nvhost_channel */ |
119 | struct channel_gk20a { | 154 | struct channel_gk20a { |
120 | struct gk20a *g; /* set only when channel is active */ | 155 | struct gk20a *g; /* set only when channel is active */ |
@@ -125,6 +160,17 @@ struct channel_gk20a { | |||
125 | bool referenceable; | 160 | bool referenceable; |
126 | atomic_t ref_count; | 161 | atomic_t ref_count; |
127 | wait_queue_head_t ref_count_dec_wq; | 162 | wait_queue_head_t ref_count_dec_wq; |
163 | #if GK20A_CHANNEL_REFCOUNT_TRACKING | ||
164 | /* | ||
165 | * Ring buffer for most recent refcount gets and puts. Protected by | ||
166 | * ref_actions_lock when getting or putting refs (i.e., adding | ||
167 | * entries), and when reading entries. | ||
168 | */ | ||
169 | struct channel_gk20a_ref_action ref_actions[ | ||
170 | GK20A_CHANNEL_REFCOUNT_TRACKING]; | ||
171 | size_t ref_actions_put; /* index of next write */ | ||
172 | spinlock_t ref_actions_lock; | ||
173 | #endif | ||
128 | 174 | ||
129 | struct gk20a_semaphore_int *hw_sema; | 175 | struct gk20a_semaphore_int *hw_sema; |
130 | 176 | ||