syncpt.c (6df633d0dc333ffce683f46f2856024479b170b9) syncpt.c (0b8070d12ee2ef62e0b07213d843eb508fba966e)
1/*
2 * Tegra host1x Syncpoints
3 *
4 * Copyright (c) 2010-2013, NVIDIA Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.

--- 100 unchanged lines hidden (view full) ---

109 */
110void host1x_syncpt_restore(struct host1x *host)
111{
112 struct host1x_syncpt *sp_base = host->syncpt;
113 unsigned int i;
114
115 for (i = 0; i < host1x_syncpt_nb_pts(host); i++)
116 host1x_hw_syncpt_restore(host, sp_base + i);
1/*
2 * Tegra host1x Syncpoints
3 *
4 * Copyright (c) 2010-2013, NVIDIA Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.

--- 100 unchanged lines hidden (view full) ---

109 */
110void host1x_syncpt_restore(struct host1x *host)
111{
112 struct host1x_syncpt *sp_base = host->syncpt;
113 unsigned int i;
114
115 for (i = 0; i < host1x_syncpt_nb_pts(host); i++)
116 host1x_hw_syncpt_restore(host, sp_base + i);
117
117 for (i = 0; i < host1x_syncpt_nb_bases(host); i++)
118 host1x_hw_syncpt_restore_wait_base(host, sp_base + i);
118 for (i = 0; i < host1x_syncpt_nb_bases(host); i++)
119 host1x_hw_syncpt_restore_wait_base(host, sp_base + i);
120
119 wmb();
120}
121
122/*
123 * Update the cached syncpoint and waitbase values by reading them
124 * from the registers.
125 */
126void host1x_syncpt_save(struct host1x *host)

--- 49 unchanged lines hidden (view full) ---

176
177/*
178 * Updated sync point form hardware, and returns true if syncpoint is expired,
179 * false if we may need to wait
180 */
181static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh)
182{
183 host1x_hw_syncpt_load(sp->host, sp);
121 wmb();
122}
123
124/*
125 * Update the cached syncpoint and waitbase values by reading them
126 * from the registers.
127 */
128void host1x_syncpt_save(struct host1x *host)

--- 49 unchanged lines hidden (view full) ---

178
179/*
180 * Updated sync point form hardware, and returns true if syncpoint is expired,
181 * false if we may need to wait
182 */
183static bool syncpt_load_min_is_expired(struct host1x_syncpt *sp, u32 thresh)
184{
185 host1x_hw_syncpt_load(sp->host, sp);
186
184 return host1x_syncpt_is_expired(sp, thresh);
185}
186
187/*
188 * Main entrypoint for syncpoint value waits.
189 */
190int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
187 return host1x_syncpt_is_expired(sp, thresh);
188}
189
190/*
191 * Main entrypoint for syncpoint value waits.
192 */
193int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
191 u32 *value)
194 u32 *value)
192{
193 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
194 void *ref;
195 struct host1x_waitlist *waiter;
196 int err = 0, check_count = 0;
197 u32 val;
198
199 if (value)
200 *value = 0;
201
202 /* first check cache */
203 if (host1x_syncpt_is_expired(sp, thresh)) {
204 if (value)
205 *value = host1x_syncpt_load(sp);
195{
196 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
197 void *ref;
198 struct host1x_waitlist *waiter;
199 int err = 0, check_count = 0;
200 u32 val;
201
202 if (value)
203 *value = 0;
204
205 /* first check cache */
206 if (host1x_syncpt_is_expired(sp, thresh)) {
207 if (value)
208 *value = host1x_syncpt_load(sp);
209
206 return 0;
207 }
208
209 /* try to read from register */
210 val = host1x_hw_syncpt_load(sp->host, sp);
211 if (host1x_syncpt_is_expired(sp, thresh)) {
212 if (value)
213 *value = val;
210 return 0;
211 }
212
213 /* try to read from register */
214 val = host1x_hw_syncpt_load(sp->host, sp);
215 if (host1x_syncpt_is_expired(sp, thresh)) {
216 if (value)
217 *value = val;
218
214 goto done;
215 }
216
217 if (!timeout) {
218 err = -EAGAIN;
219 goto done;
220 }
221

--- 14 unchanged lines hidden (view full) ---

236 err = -EAGAIN;
237 /* Caller-specified timeout may be impractically low */
238 if (timeout < 0)
239 timeout = LONG_MAX;
240
241 /* wait for the syncpoint, or timeout, or signal */
242 while (timeout) {
243 long check = min_t(long, SYNCPT_CHECK_PERIOD, timeout);
219 goto done;
220 }
221
222 if (!timeout) {
223 err = -EAGAIN;
224 goto done;
225 }
226

--- 14 unchanged lines hidden (view full) ---

241 err = -EAGAIN;
242 /* Caller-specified timeout may be impractically low */
243 if (timeout < 0)
244 timeout = LONG_MAX;
245
246 /* wait for the syncpoint, or timeout, or signal */
247 while (timeout) {
248 long check = min_t(long, SYNCPT_CHECK_PERIOD, timeout);
244 int remain = wait_event_interruptible_timeout(wq,
249 int remain;
250
251 remain = wait_event_interruptible_timeout(wq,
245 syncpt_load_min_is_expired(sp, thresh),
246 check);
247 if (remain > 0 || host1x_syncpt_is_expired(sp, thresh)) {
248 if (value)
249 *value = host1x_syncpt_load(sp);
252 syncpt_load_min_is_expired(sp, thresh),
253 check);
254 if (remain > 0 || host1x_syncpt_is_expired(sp, thresh)) {
255 if (value)
256 *value = host1x_syncpt_load(sp);
257
250 err = 0;
258 err = 0;
259
251 break;
252 }
260 break;
261 }
262
253 if (remain < 0) {
254 err = remain;
255 break;
256 }
263 if (remain < 0) {
264 err = remain;
265 break;
266 }
267
257 timeout -= check;
268 timeout -= check;
269
258 if (timeout && check_count <= MAX_STUCK_CHECK_COUNT) {
259 dev_warn(sp->host->dev,
260 "%s: syncpoint id %u (%s) stuck waiting %d, timeout=%ld\n",
261 current->comm, sp->id, sp->name,
262 thresh, timeout);
263
264 host1x_debug_dump_syncpts(sp->host);
270 if (timeout && check_count <= MAX_STUCK_CHECK_COUNT) {
271 dev_warn(sp->host->dev,
272 "%s: syncpoint id %u (%s) stuck waiting %d, timeout=%ld\n",
273 current->comm, sp->id, sp->name,
274 thresh, timeout);
275
276 host1x_debug_dump_syncpts(sp->host);
277
265 if (check_count == MAX_STUCK_CHECK_COUNT)
266 host1x_debug_dump(sp->host);
278 if (check_count == MAX_STUCK_CHECK_COUNT)
279 host1x_debug_dump(sp->host);
280
267 check_count++;
268 }
269 }
281 check_count++;
282 }
283 }
284
270 host1x_intr_put_ref(sp->host, sp->id, ref);
271
272done:
273 return err;
274}
275EXPORT_SYMBOL(host1x_syncpt_wait);
276
277/*
278 * Returns true if syncpoint is expired, false if we may need to wait
279 */
280bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh)
281{
282 u32 current_val;
283 u32 future_val;
284
285 smp_rmb();
285 host1x_intr_put_ref(sp->host, sp->id, ref);
286
287done:
288 return err;
289}
290EXPORT_SYMBOL(host1x_syncpt_wait);
291
292/*
293 * Returns true if syncpoint is expired, false if we may need to wait
294 */
295bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh)
296{
297 u32 current_val;
298 u32 future_val;
299
300 smp_rmb();
301
286 current_val = (u32)atomic_read(&sp->min_val);
287 future_val = (u32)atomic_read(&sp->max_val);
288
289 /* Note the use of unsigned arithmetic here (mod 1<<32).
290 *
291 * c = current_val = min_val = the current value of the syncpoint.
292 * t = thresh = the value we are checking
293 * f = future_val = max_val = the value c will reach when all

--- 82 unchanged lines hidden (view full) ---

376
377 return 0;
378}
379
380struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
381 unsigned long flags)
382{
383 struct host1x *host = dev_get_drvdata(dev->parent);
302 current_val = (u32)atomic_read(&sp->min_val);
303 future_val = (u32)atomic_read(&sp->max_val);
304
305 /* Note the use of unsigned arithmetic here (mod 1<<32).
306 *
307 * c = current_val = min_val = the current value of the syncpoint.
308 * t = thresh = the value we are checking
309 * f = future_val = max_val = the value c will reach when all

--- 82 unchanged lines hidden (view full) ---

392
393 return 0;
394}
395
396struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
397 unsigned long flags)
398{
399 struct host1x *host = dev_get_drvdata(dev->parent);
400
384 return host1x_syncpt_alloc(host, dev, flags);
385}
386EXPORT_SYMBOL(host1x_syncpt_request);
387
388void host1x_syncpt_free(struct host1x_syncpt *sp)
389{
390 if (!sp)
391 return;

--- 18 unchanged lines hidden (view full) ---

410
411/*
412 * Read max. It indicates how many operations there are in queue, either in
413 * channel or in a software thread.
414 */
415u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
416{
417 smp_rmb();
401 return host1x_syncpt_alloc(host, dev, flags);
402}
403EXPORT_SYMBOL(host1x_syncpt_request);
404
405void host1x_syncpt_free(struct host1x_syncpt *sp)
406{
407 if (!sp)
408 return;

--- 18 unchanged lines hidden (view full) ---

427
428/*
429 * Read max. It indicates how many operations there are in queue, either in
430 * channel or in a software thread.
431 */
432u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
433{
434 smp_rmb();
435
418 return (u32)atomic_read(&sp->max_val);
419}
420EXPORT_SYMBOL(host1x_syncpt_read_max);
421
422/*
423 * Read min, which is a shadow of the current sync point value in hardware.
424 */
425u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
426{
427 smp_rmb();
436 return (u32)atomic_read(&sp->max_val);
437}
438EXPORT_SYMBOL(host1x_syncpt_read_max);
439
440/*
441 * Read min, which is a shadow of the current sync point value in hardware.
442 */
443u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
444{
445 smp_rmb();
446
428 return (u32)atomic_read(&sp->min_val);
429}
430EXPORT_SYMBOL(host1x_syncpt_read_min);
431
432u32 host1x_syncpt_read(struct host1x_syncpt *sp)
433{
434 return host1x_syncpt_load(sp);
435}

--- 13 unchanged lines hidden (view full) ---

449{
450 return host->info->nb_mlocks;
451}
452
453struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, unsigned int id)
454{
455 if (host->info->nb_pts < id)
456 return NULL;
447 return (u32)atomic_read(&sp->min_val);
448}
449EXPORT_SYMBOL(host1x_syncpt_read_min);
450
451u32 host1x_syncpt_read(struct host1x_syncpt *sp)
452{
453 return host1x_syncpt_load(sp);
454}

--- 13 unchanged lines hidden (view full) ---

468{
469 return host->info->nb_mlocks;
470}
471
472struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, unsigned int id)
473{
474 if (host->info->nb_pts < id)
475 return NULL;
476
457 return host->syncpt + id;
458}
459EXPORT_SYMBOL(host1x_syncpt_get);
460
461struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
462{
463 return sp ? sp->base : NULL;
464}
465EXPORT_SYMBOL(host1x_syncpt_get_base);
466
467u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
468{
469 return base->id;
470}
471EXPORT_SYMBOL(host1x_syncpt_base_id);
477 return host->syncpt + id;
478}
479EXPORT_SYMBOL(host1x_syncpt_get);
480
481struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
482{
483 return sp ? sp->base : NULL;
484}
485EXPORT_SYMBOL(host1x_syncpt_get_base);
486
487u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
488{
489 return base->id;
490}
491EXPORT_SYMBOL(host1x_syncpt_base_id);