aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/syncpt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/syncpt.c')
-rw-r--r--drivers/gpu/host1x/syncpt.c92
1 files changed, 83 insertions, 9 deletions
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 409745b949db..159c479829c9 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -30,9 +30,32 @@
30#define SYNCPT_CHECK_PERIOD (2 * HZ) 30#define SYNCPT_CHECK_PERIOD (2 * HZ)
31#define MAX_STUCK_CHECK_COUNT 15 31#define MAX_STUCK_CHECK_COUNT 15
32 32
33static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host, 33static struct host1x_syncpt_base *
34 struct device *dev, 34host1x_syncpt_base_request(struct host1x *host)
35 bool client_managed) 35{
36 struct host1x_syncpt_base *bases = host->bases;
37 unsigned int i;
38
39 for (i = 0; i < host->info->nb_bases; i++)
40 if (!bases[i].requested)
41 break;
42
43 if (i >= host->info->nb_bases)
44 return NULL;
45
46 bases[i].requested = true;
47 return &bases[i];
48}
49
50static void host1x_syncpt_base_free(struct host1x_syncpt_base *base)
51{
52 if (base)
53 base->requested = false;
54}
55
56static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
57 struct device *dev,
58 unsigned long flags)
36{ 59{
37 int i; 60 int i;
38 struct host1x_syncpt *sp = host->syncpt; 61 struct host1x_syncpt *sp = host->syncpt;
@@ -44,6 +67,12 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
44 if (i >= host->info->nb_pts) 67 if (i >= host->info->nb_pts)
45 return NULL; 68 return NULL;
46 69
70 if (flags & HOST1X_SYNCPT_HAS_BASE) {
71 sp->base = host1x_syncpt_base_request(host);
72 if (!sp->base)
73 return NULL;
74 }
75
47 name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id, 76 name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id,
48 dev ? dev_name(dev) : NULL); 77 dev ? dev_name(dev) : NULL);
49 if (!name) 78 if (!name)
@@ -51,7 +80,11 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
51 80
52 sp->dev = dev; 81 sp->dev = dev;
53 sp->name = name; 82 sp->name = name;
54 sp->client_managed = client_managed; 83
84 if (flags & HOST1X_SYNCPT_CLIENT_MANAGED)
85 sp->client_managed = true;
86 else
87 sp->client_managed = false;
55 88
56 return sp; 89 return sp;
57} 90}
@@ -303,25 +336,35 @@ int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
303 336
304int host1x_syncpt_init(struct host1x *host) 337int host1x_syncpt_init(struct host1x *host)
305{ 338{
339 struct host1x_syncpt_base *bases;
306 struct host1x_syncpt *syncpt; 340 struct host1x_syncpt *syncpt;
307 int i; 341 int i;
308 342
309 syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts, 343 syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts,
310 GFP_KERNEL); 344 GFP_KERNEL);
311 if (!syncpt) 345 if (!syncpt)
312 return -ENOMEM; 346 return -ENOMEM;
313 347
314 for (i = 0; i < host->info->nb_pts; ++i) { 348 bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases,
349 GFP_KERNEL);
350 if (!bases)
351 return -ENOMEM;
352
353 for (i = 0; i < host->info->nb_pts; i++) {
315 syncpt[i].id = i; 354 syncpt[i].id = i;
316 syncpt[i].host = host; 355 syncpt[i].host = host;
317 } 356 }
318 357
358 for (i = 0; i < host->info->nb_bases; i++)
359 bases[i].id = i;
360
319 host->syncpt = syncpt; 361 host->syncpt = syncpt;
362 host->bases = bases;
320 363
321 host1x_syncpt_restore(host); 364 host1x_syncpt_restore(host);
322 365
323 /* Allocate sync point to use for clearing waits for expired fences */ 366 /* Allocate sync point to use for clearing waits for expired fences */
324 host->nop_sp = _host1x_syncpt_alloc(host, NULL, false); 367 host->nop_sp = host1x_syncpt_alloc(host, NULL, 0);
325 if (!host->nop_sp) 368 if (!host->nop_sp)
326 return -ENOMEM; 369 return -ENOMEM;
327 370
@@ -329,10 +372,10 @@ int host1x_syncpt_init(struct host1x *host)
329} 372}
330 373
331struct host1x_syncpt *host1x_syncpt_request(struct device *dev, 374struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
332 bool client_managed) 375 unsigned long flags)
333{ 376{
334 struct host1x *host = dev_get_drvdata(dev->parent); 377 struct host1x *host = dev_get_drvdata(dev->parent);
335 return _host1x_syncpt_alloc(host, dev, client_managed); 378 return host1x_syncpt_alloc(host, dev, flags);
336} 379}
337 380
338void host1x_syncpt_free(struct host1x_syncpt *sp) 381void host1x_syncpt_free(struct host1x_syncpt *sp)
@@ -340,7 +383,9 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
340 if (!sp) 383 if (!sp)
341 return; 384 return;
342 385
386 host1x_syncpt_base_free(sp->base);
343 kfree(sp->name); 387 kfree(sp->name);
388 sp->base = NULL;
344 sp->dev = NULL; 389 sp->dev = NULL;
345 sp->name = NULL; 390 sp->name = NULL;
346 sp->client_managed = false; 391 sp->client_managed = false;
@@ -354,6 +399,25 @@ void host1x_syncpt_deinit(struct host1x *host)
354 kfree(sp->name); 399 kfree(sp->name);
355} 400}
356 401
402/*
403 * Read max. It indicates how many operations there are in queue, either in
404 * channel or in a software thread.
405 * */
406u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
407{
408 smp_rmb();
409 return (u32)atomic_read(&sp->max_val);
410}
411
412/*
413 * Read min, which is a shadow of the current sync point value in hardware.
414 */
415u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
416{
417 smp_rmb();
418 return (u32)atomic_read(&sp->min_val);
419}
420
357int host1x_syncpt_nb_pts(struct host1x *host) 421int host1x_syncpt_nb_pts(struct host1x *host)
358{ 422{
359 return host->info->nb_pts; 423 return host->info->nb_pts;
@@ -375,3 +439,13 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id)
375 return NULL; 439 return NULL;
376 return host->syncpt + id; 440 return host->syncpt + id;
377} 441}
442
443struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
444{
445 return sp ? sp->base : NULL;
446}
447
448u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
449{
450 return base->id;
451}