diff options
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r-- | drivers/gpu/host1x/bus.c | 79 | ||||
-rw-r--r-- | drivers/gpu/host1x/dev.c | 4 | ||||
-rw-r--r-- | drivers/gpu/host1x/job.c | 21 | ||||
-rw-r--r-- | drivers/gpu/host1x/syncpt.c | 2 |
4 files changed, 86 insertions, 20 deletions
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 2c8559ff3481..6a995db51d6d 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -120,7 +120,7 @@ static void host1x_subdev_register(struct host1x_device *device, mutex_lock(&device->clients_lock); list_move_tail(&client->list, &device->clients); list_move_tail(&subdev->list, &device->active); - client->parent = &device->dev; + client->host = &device->dev; subdev->client = client; mutex_unlock(&device->clients_lock); mutex_unlock(&device->subdevs_lock); @@ -156,7 +156,7 @@ static void __host1x_subdev_unregister(struct host1x_device *device, */ mutex_lock(&device->clients_lock); subdev->client = NULL; - client->parent = NULL; + client->host = NULL; list_move_tail(&subdev->list, &device->subdevs); /* * XXX: Perhaps don't do this here, but rather explicitly remove it @@ -710,6 +710,10 @@ int host1x_client_register(struct host1x_client *client) struct host1x *host1x; int err; + INIT_LIST_HEAD(&client->list); + mutex_init(&client->lock); + client->usecount = 0; + mutex_lock(&devices_lock); list_for_each_entry(host1x, &devices, list) { @@ -768,3 +772,74 @@ int host1x_client_unregister(struct host1x_client *client) return 0; } EXPORT_SYMBOL(host1x_client_unregister); + +int host1x_client_suspend(struct host1x_client *client) +{ + int err = 0; + + mutex_lock(&client->lock); + + if (client->usecount == 1) { + if (client->ops && client->ops->suspend) { + err = client->ops->suspend(client); + if (err < 0) + goto unlock; + } + } + + client->usecount--; + dev_dbg(client->dev, "use count: %u\n", client->usecount); + + if (client->parent) { + err = host1x_client_suspend(client->parent); + if (err < 0) + goto resume; + } + + goto unlock; + +resume: + if (client->usecount == 0) + if (client->ops && client->ops->resume) + client->ops->resume(client); + + client->usecount++; +unlock: + mutex_unlock(&client->lock); + return err; +} +EXPORT_SYMBOL(host1x_client_suspend); + +int host1x_client_resume(struct host1x_client *client) +{ + int err = 0; + + mutex_lock(&client->lock); + + if (client->parent) { + err = host1x_client_resume(client->parent); + if (err < 0) + goto unlock; + } + + if (client->usecount == 0) { + if (client->ops && client->ops->resume) { + err = client->ops->resume(client); + if (err < 0) + goto suspend; + } + } + + client->usecount++; + dev_dbg(client->dev, "use count: %u\n", client->usecount); + + goto unlock; + +suspend: + if (client->parent) + host1x_client_suspend(client->parent); +unlock: + mutex_unlock(&client->lock); + return err; +} +EXPORT_SYMBOL(host1x_client_resume); diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index a738ea55e407..388bcc2889aa 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -339,10 +339,8 @@ static int host1x_probe(struct platform_device *pdev) } syncpt_irq = platform_get_irq(pdev, 0); - if (syncpt_irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ: %d\n", syncpt_irq); + if (syncpt_irq < 0) return syncpt_irq; - } mutex_init(&host->devices_lock); INIT_LIST_HEAD(&host->devices); diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index 25ca54de8fc5..60b2fedd0061 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -244,8 +244,7 @@ unpin: static int do_relocs(struct host1x_job *job, struct host1x_job_gather *g) { - u32 last_page = ~0; - void *cmdbuf_page_addr = NULL; + void *cmdbuf_addr = NULL; struct host1x_bo *cmdbuf = g->bo; unsigned int i; @@ -267,28 +266,22 @@ static int do_relocs(struct host1x_job *job, struct host1x_job_gather *g) goto patch_reloc; } - if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) { - if (cmdbuf_page_addr) - host1x_bo_kunmap(cmdbuf, last_page, - cmdbuf_page_addr); + if (!cmdbuf_addr) { + cmdbuf_addr = host1x_bo_mmap(cmdbuf); - cmdbuf_page_addr = host1x_bo_kmap(cmdbuf, - reloc->cmdbuf.offset >> PAGE_SHIFT); - last_page = reloc->cmdbuf.offset >> PAGE_SHIFT; - - if (unlikely(!cmdbuf_page_addr)) { + if (unlikely(!cmdbuf_addr)) { pr_err("Could not map cmdbuf for relocation\n"); return -ENOMEM; } } - target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK); + target = cmdbuf_addr + reloc->cmdbuf.offset; patch_reloc: *target = reloc_addr; } - if (cmdbuf_page_addr) - host1x_bo_kunmap(cmdbuf, last_page, cmdbuf_page_addr); + if (cmdbuf_addr) + host1x_bo_munmap(cmdbuf, cmdbuf_addr); return 0; } diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index dd1cd0142941..fce7892d5137 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -421,7 +421,7 @@ int host1x_syncpt_init(struct host1x *host) struct host1x_syncpt *host1x_syncpt_request(struct host1x_client *client, unsigned long flags) { - struct host1x *host = dev_get_drvdata(client->parent->parent); + struct host1x *host = dev_get_drvdata(client->host->parent); return host1x_syncpt_alloc(host, client, flags); } |