diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2017-02-01 03:28:38 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-03-02 20:51:03 -0500 |
commit | f1072a28be09dc7f5433b5e1013a76d8a87c2505 (patch) | |
tree | 68d1a5b5123834859f8ae8c4481b886b49364811 /drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |
parent | 0c155313e75a82a409d3438cc982ee30bb453d16 (diff) |
gpu: nvgpu: add worker for watchdog and job cleanup
Implement a worker thread to replace the delayed works in channel
watchdog and job cleanups. Watchdog runs by polling the channel states
periodically, and job cleanup is performed on channels that are appended
on a work queue consumed by the worker thread. Handling both of these
two in the same thread makes it impossible for them to cause a deadlock,
as has previously happened.
The watchdog takes references to channels during checking and possibly
recovering channels. Jobs in the cleanup queue have an additional
reference taken which is released after the channel is processed. The
worker is woken up from periodic sleep when channels are added to the
queue.
Currently, the queue is only used for job cleanups, but it is extendable
for other per-channel works too. The worker can also process other
periodic actions dependent on channels.
Neither the semantics of timeout handling or of job cleanups are yet
significantly changed - this patch only serializes them into one
background thread.
Each job that needs cleanup is tracked and holds a reference to its
channel and a power reference, and timeouts can only be processed on
channels that are tracked, so the thread will always be idle if the
system is going to be suspended, so there is currently no need to
explicitly suspend or stop it.
Bug 1848834
Bug 1851689
Bug 1814773
Bug 200270332
Jira NVGPU-21
Change-Id: I355101802f50841ea9bd8042a017f91c931d2dc7
Signed-off-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-on: http://git-master/r/1297183
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 | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 14ee9f69..d9913cd7 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <uapi/linux/nvgpu.h> | 27 | #include <uapi/linux/nvgpu.h> |
28 | 28 | ||
29 | #include <nvgpu/lock.h> | 29 | #include <nvgpu/lock.h> |
30 | #include <nvgpu/timers.h> | ||
30 | 31 | ||
31 | struct gk20a; | 32 | struct gk20a; |
32 | struct gr_gk20a; | 33 | struct gr_gk20a; |
@@ -87,12 +88,19 @@ struct channel_gk20a_joblist { | |||
87 | struct list_head jobs; | 88 | struct list_head jobs; |
88 | struct nvgpu_spinlock lock; | 89 | struct nvgpu_spinlock lock; |
89 | } dynamic; | 90 | } dynamic; |
91 | |||
92 | /* | ||
93 | * Synchronize abort cleanup (when closing a channel) and job cleanup | ||
94 | * (asynchronously from worker) - protect from concurrent access when | ||
95 | * job resources are being freed. | ||
96 | */ | ||
97 | struct nvgpu_mutex cleanup_lock; | ||
90 | }; | 98 | }; |
91 | 99 | ||
92 | struct channel_gk20a_timeout { | 100 | struct channel_gk20a_timeout { |
93 | struct delayed_work wq; | ||
94 | struct nvgpu_raw_spinlock lock; | 101 | struct nvgpu_raw_spinlock lock; |
95 | bool initialized; | 102 | struct nvgpu_timeout timer; |
103 | bool running; | ||
96 | u32 gp_get; | 104 | u32 gp_get; |
97 | }; | 105 | }; |
98 | 106 | ||
@@ -110,12 +118,6 @@ struct gk20a_event_id_data { | |||
110 | struct list_head event_id_node; | 118 | struct list_head event_id_node; |
111 | }; | 119 | }; |
112 | 120 | ||
113 | struct channel_gk20a_clean_up { | ||
114 | struct nvgpu_mutex lock; | ||
115 | bool scheduled; | ||
116 | struct delayed_work wq; | ||
117 | }; | ||
118 | |||
119 | /* | 121 | /* |
120 | * Track refcount actions, saving their stack traces. This number specifies how | 122 | * 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 | 123 | * many most recent actions are stored in a buffer. Set to 0 to disable. 128 |
@@ -214,7 +216,8 @@ struct channel_gk20a { | |||
214 | u32 timeout_gpfifo_get; | 216 | u32 timeout_gpfifo_get; |
215 | 217 | ||
216 | struct channel_gk20a_timeout timeout; | 218 | struct channel_gk20a_timeout timeout; |
217 | struct channel_gk20a_clean_up clean_up; | 219 | /* for job cleanup handling in the background worker */ |
220 | struct list_head worker_item; | ||
218 | 221 | ||
219 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 222 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
220 | struct { | 223 | struct { |
@@ -250,8 +253,11 @@ struct channel_gk20a { | |||
250 | u64 virt_ctx; | 253 | u64 virt_ctx; |
251 | #endif | 254 | #endif |
252 | 255 | ||
253 | /* signal channel owner via a callback, if set, in gk20a_channel_update | 256 | /* |
254 | * via schedule_work */ | 257 | * Signal channel owner via a callback, if set, in job cleanup with |
258 | * schedule_work. Means that something finished on the channel (perhaps | ||
259 | * more than one job). | ||
260 | */ | ||
255 | void (*update_fn)(struct channel_gk20a *, void *); | 261 | void (*update_fn)(struct channel_gk20a *, void *); |
256 | void *update_fn_data; | 262 | void *update_fn_data; |
257 | struct nvgpu_spinlock update_fn_lock; /* make access to the two above atomic */ | 263 | struct nvgpu_spinlock update_fn_lock; /* make access to the two above atomic */ |
@@ -293,6 +299,9 @@ int gk20a_disable_channel_tsg(struct gk20a *g, struct channel_gk20a *ch); | |||
293 | int gk20a_channel_suspend(struct gk20a *g); | 299 | int gk20a_channel_suspend(struct gk20a *g); |
294 | int gk20a_channel_resume(struct gk20a *g); | 300 | int gk20a_channel_resume(struct gk20a *g); |
295 | 301 | ||
302 | int nvgpu_channel_worker_init(struct gk20a *g); | ||
303 | void nvgpu_channel_worker_deinit(struct gk20a *g); | ||
304 | |||
296 | /* Channel file operations */ | 305 | /* Channel file operations */ |
297 | int gk20a_channel_open(struct inode *inode, struct file *filp); | 306 | int gk20a_channel_open(struct inode *inode, struct file *filp); |
298 | int gk20a_channel_open_ioctl(struct gk20a *g, | 307 | int gk20a_channel_open_ioctl(struct gk20a *g, |
@@ -302,7 +311,7 @@ long gk20a_channel_ioctl(struct file *filp, | |||
302 | unsigned long arg); | 311 | unsigned long arg); |
303 | int gk20a_channel_release(struct inode *inode, struct file *filp); | 312 | int gk20a_channel_release(struct inode *inode, struct file *filp); |
304 | struct channel_gk20a *gk20a_get_channel_from_file(int fd); | 313 | struct channel_gk20a *gk20a_get_channel_from_file(int fd); |
305 | void gk20a_channel_update(struct channel_gk20a *c, int nr_completed); | 314 | void gk20a_channel_update(struct channel_gk20a *c); |
306 | 315 | ||
307 | void gk20a_init_channel(struct gpu_ops *gops); | 316 | void gk20a_init_channel(struct gpu_ops *gops); |
308 | 317 | ||