diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2012-03-27 15:43:58 +0300 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-04-05 08:52:08 -0700 |
commit | 589961040a88d132939eb34d211d8e8b9921b446 (patch) | |
tree | 290195a349d77548add278918964ba18de8cc9af /drivers/video | |
parent | b5e2ad69b5f5cc13f5a96b09335896d6d5dbed78 (diff) |
video: tegra: host: Add syncpt sysfs entries
Expose sync point current and max values through sysfs.
Bug 957639
Change-Id: I2a3b914d404bb8d7bbed86d383c859bd8237a278
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/92778
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/tegra/host/dev.c | 33 | ||||
-rw-r--r-- | drivers/video/tegra/host/host1x/host1x_syncpt.c | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_syncpt.c | 124 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_syncpt.h | 13 |
4 files changed, 145 insertions, 29 deletions
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index 0425368e6f81..50d8d2dbe07b 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -367,20 +367,8 @@ static void nvhost_remove_chip_support(struct nvhost_master *host) kfree(host->channels); host->channels = 0; - kfree(host->syncpt.min_val); - host->syncpt.min_val = 0; - - kfree(host->syncpt.max_val); - host->syncpt.max_val = 0; - - kfree(host->syncpt.base_val); - host->syncpt.base_val = 0; - kfree(host->intr.syncpt); host->intr.syncpt = 0; - - kfree(host->syncpt.lock_counts); - host->syncpt.lock_counts = 0; } static int __devinit nvhost_init_chip_support(struct nvhost_master *host) @@ -405,24 +393,10 @@ static int __devinit nvhost_init_chip_support(struct nvhost_master *host) host->channels = kzalloc(sizeof(struct nvhost_channel) * host->nb_channels, GFP_KERNEL); - host->syncpt.min_val = kzalloc(sizeof(atomic_t) * - host->syncpt.nb_pts, GFP_KERNEL); - - host->syncpt.max_val = kzalloc(sizeof(atomic_t) * - host->syncpt.nb_pts, GFP_KERNEL); - - host->syncpt.base_val = kzalloc(sizeof(u32) * - host->syncpt.nb_bases, GFP_KERNEL); - host->intr.syncpt = kzalloc(sizeof(struct nvhost_intr_syncpt) * host->syncpt.nb_pts, GFP_KERNEL); - host->syncpt.lock_counts = kzalloc(sizeof(atomic_t) * - host->syncpt.nb_mlocks, GFP_KERNEL); - - if (!(host->channels && host->syncpt.min_val && - host->syncpt.max_val && host->syncpt.base_val && - host->intr.syncpt && host->syncpt.lock_counts)) { + if (!(host->channels && host->intr.syncpt)) { /* frees happen in the support removal phase */ return -ENOMEM; } @@ -539,6 +513,10 @@ static int __devinit nvhost_probe(struct nvhost_device *dev) nvhost_bus_add_host(host); + err = nvhost_syncpt_init(&tegra_grhost_device, &host->syncpt); + if (err) + goto fail; + err = nvhost_intr_init(&host->intr, intr1->start, intr0->start); if (err) goto fail; @@ -574,6 +552,7 @@ static int __exit nvhost_remove(struct nvhost_device *dev) { struct nvhost_master *host = nvhost_get_drvdata(dev); nvhost_intr_deinit(&host->intr); + nvhost_syncpt_deinit(&host->syncpt); nvhost_remove_chip_support(host); return 0; } diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.c b/drivers/video/tegra/host/host1x/host1x_syncpt.c index b0fd9970aaa0..b431fa350638 100644 --- a/drivers/video/tegra/host/host1x/host1x_syncpt.c +++ b/drivers/video/tegra/host/host1x/host1x_syncpt.c @@ -71,8 +71,10 @@ static u32 t20_syncpt_update_min(struct nvhost_syncpt *sp, u32 id) if (!nvhost_syncpt_check_max(sp, id, live)) dev_err(&syncpt_to_dev(sp)->dev->dev, - "%s failed: id=%u\n", + "%s failed: id=%u, min=%d, max=%d\n", __func__, + nvhost_syncpt_read_min(sp, id), + nvhost_syncpt_read_max(sp, id), id); return live; diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c index eb5176ea1bf5..13ad0fc3a3cf 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.c +++ b/drivers/video/tegra/host/nvhost_syncpt.c @@ -20,10 +20,15 @@ #include <linux/nvhost_ioctl.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include "nvhost_syncpt.h" #include "dev.h" #define MAX_STUCK_CHECK_COUNT 15 +#define MAX_SYNCPT_LENGTH 5 +/* Name of sysfs node for min and max value */ +static const char *min_name = "min"; +static const char *max_name = "max"; /** * Resets syncpoint and waitbase values to sw shadows @@ -317,3 +322,122 @@ int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp, return syncpt_op(sp).wait_check(sp, nvmap, waitchk_mask, wait, num_waitchk); } + +/* Displays the current value of the sync point via sysfs */ +static ssize_t syncpt_min_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct nvhost_syncpt_attr *syncpt_attr = + container_of(attr, struct nvhost_syncpt_attr, attr); + + return snprintf(buf, PAGE_SIZE, "%d", + nvhost_syncpt_read(&syncpt_attr->host->syncpt, + syncpt_attr->id)); +} + +static ssize_t syncpt_max_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct nvhost_syncpt_attr *syncpt_attr = + container_of(attr, struct nvhost_syncpt_attr, attr); + + return snprintf(buf, PAGE_SIZE, "%d", + nvhost_syncpt_read_max(&syncpt_attr->host->syncpt, + syncpt_attr->id)); +} + +int nvhost_syncpt_init(struct nvhost_device *dev, + struct nvhost_syncpt *sp) +{ + int i; + struct nvhost_master *host = syncpt_to_dev(sp); + int err = 0; + + /* Allocate structs for min, max and base values */ + sp->min_val = kzalloc(sizeof(atomic_t) * sp->nb_pts, GFP_KERNEL); + sp->max_val = kzalloc(sizeof(atomic_t) * sp->nb_pts, GFP_KERNEL); + sp->base_val = kzalloc(sizeof(u32) * sp->nb_bases, GFP_KERNEL); + sp->lock_counts = kzalloc(sizeof(atomic_t) * sp->nb_mlocks, GFP_KERNEL); + + if (!(sp->min_val && sp->max_val && sp->base_val && sp->lock_counts)) { + /* frees happen in the deinit */ + err = -ENOMEM; + goto fail; + } + + sp->kobj = kobject_create_and_add("syncpt", &dev->dev.kobj); + if (!sp->kobj) { + err = -EIO; + goto fail; + } + + /* Allocate two attributes for each sync point: min and max */ + sp->syncpt_attrs = kzalloc(sizeof(*sp->syncpt_attrs) * sp->nb_pts * 2, + GFP_KERNEL); + if (!sp->syncpt_attrs) { + err = -ENOMEM; + goto fail; + } + + /* Fill in the attributes */ + for (i = 0; i < sp->nb_pts; i++) { + char name[MAX_SYNCPT_LENGTH]; + struct kobject *kobj; + struct nvhost_syncpt_attr *min = &sp->syncpt_attrs[i*2]; + struct nvhost_syncpt_attr *max = &sp->syncpt_attrs[i*2+1]; + + /* Create one directory per sync point */ + snprintf(name, sizeof(name), "%d", i); + kobj = kobject_create_and_add(name, sp->kobj); + if (!kobj) { + err = -EIO; + goto fail; + } + + min->id = i; + min->host = host; + min->attr.attr.name = min_name; + min->attr.attr.mode = S_IRUGO; + min->attr.show = syncpt_min_show; + if (sysfs_create_file(kobj, &min->attr.attr)) { + err = -EIO; + goto fail; + } + + max->id = i; + max->host = host; + max->attr.attr.name = max_name; + max->attr.attr.mode = S_IRUGO; + max->attr.show = syncpt_max_show; + if (sysfs_create_file(kobj, &max->attr.attr)) { + err = -EIO; + goto fail; + } + } + + return err; + +fail: + nvhost_syncpt_deinit(sp); + return err; +} + +void nvhost_syncpt_deinit(struct nvhost_syncpt *sp) +{ + kobject_put(sp->kobj); + + kfree(sp->min_val); + sp->min_val = NULL; + + kfree(sp->max_val); + sp->max_val = NULL; + + kfree(sp->base_val); + sp->base_val = NULL; + + kfree(sp->lock_counts); + sp->lock_counts = 0; + + kfree(sp->syncpt_attrs); + sp->syncpt_attrs = NULL; +} diff --git a/drivers/video/tegra/host/nvhost_syncpt.h b/drivers/video/tegra/host/nvhost_syncpt.h index 5b339178d1e1..b71cb3e6287e 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.h +++ b/drivers/video/tegra/host/nvhost_syncpt.h @@ -34,7 +34,15 @@ struct nvhost_waitchk; #define NVSYNCPT_GRAPHICS_HOST (0) #define NVSYNCPT_INVALID (-1) +/* Attribute struct for sysfs min and max attributes */ +struct nvhost_syncpt_attr { + struct kobj_attribute attr; + struct nvhost_master *host; + int id; +}; + struct nvhost_syncpt { + struct kobject *kobj; atomic_t *min_val; atomic_t *max_val; u32 *base_val; @@ -43,9 +51,12 @@ struct nvhost_syncpt { u32 client_managed; atomic_t *lock_counts; u32 nb_mlocks; + struct nvhost_syncpt_attr *syncpt_attrs; }; -int nvhost_syncpt_init(struct nvhost_syncpt *); +int nvhost_syncpt_init(struct nvhost_device *, struct nvhost_syncpt *); +void nvhost_syncpt_deinit(struct nvhost_syncpt *); + #define client_managed(id) (BIT(id) & sp->client_managed) #define syncpt_to_dev(sp) container_of(sp, struct nvhost_master, syncpt) #define syncpt_op(sp) (syncpt_to_dev(sp)->op.syncpt) |