Exemplo n.º 1
0
static int nvhost_ctrlopen(struct inode *inode, struct file *filp)
{
	struct nvhost_master *host =
		container_of(inode->i_cdev, struct nvhost_master, cdev);
	struct nvhost_ctrl_userctx *priv;
	u32 *mod_locks;

	trace_nvhost_ctrlopen(host->dev->name);

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	mod_locks = kzalloc(sizeof(u32)
			* nvhost_syncpt_nb_mlocks(&host->syncpt),
			GFP_KERNEL);

	if (!(priv && mod_locks)) {
		kfree(priv);
		kfree(mod_locks);
		return -ENOMEM;
	}

	priv->dev = host;
	priv->mod_locks = mod_locks;
	filp->private_data = priv;
	return 0;
}
Exemplo n.º 2
0
static int nvhost_ioctl_ctrl_module_mutex(struct nvhost_ctrl_userctx *ctx,
	struct nvhost_ctrl_module_mutex_args *args)
{
	int err = 0;
	if (args->id >= nvhost_syncpt_nb_mlocks(&ctx->dev->syncpt) ||
	    args->lock > 1)
		return -EINVAL;

	trace_nvhost_ioctl_ctrl_module_mutex(args->lock, args->id);
	if (args->lock && !ctx->mod_locks[args->id]) {
		if (args->id == 0)
			nvhost_module_busy(ctx->dev->dev);
		else
			err = nvhost_mutex_try_lock(&ctx->dev->syncpt,
					args->id);
		if (!err)
			ctx->mod_locks[args->id] = 1;
	} else if (!args->lock && ctx->mod_locks[args->id]) {
		if (args->id == 0)
			nvhost_module_idle(ctx->dev->dev);
		else
			nvhost_mutex_unlock(&ctx->dev->syncpt, args->id);
		ctx->mod_locks[args->id] = 0;
	}
	return err;
}
Exemplo n.º 3
0
static int nvhost_ctrlrelease(struct inode *inode, struct file *filp)
{
	struct nvhost_ctrl_userctx *priv = filp->private_data;
	int i;

	trace_nvhost_ctrlrelease(priv->dev->dev->name);

	filp->private_data = NULL;
	if (priv->mod_locks[0])
		nvhost_module_idle(priv->dev->dev);
	for (i = 1; i < nvhost_syncpt_nb_mlocks(&priv->dev->syncpt); i++)
		if (priv->mod_locks[i])
			nvhost_mutex_unlock(&priv->dev->syncpt, i);
	kfree(priv->mod_locks);
	kfree(priv);
	return 0;
}
Exemplo n.º 4
0
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) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->max_val = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->base_val = kzalloc(sizeof(u32) * nvhost_syncpt_nb_bases(sp),
			GFP_KERNEL);
	sp->lock_counts =
		kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_mlocks(sp),
			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)
			* nvhost_syncpt_nb_pts(sp) * 2, GFP_KERNEL);
	if (!sp->syncpt_attrs) {
		err = -ENOMEM;
		goto fail;
	}

	/* Fill in the attributes */
	for (i = 0; i < nvhost_syncpt_nb_pts(sp); 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;
}
int nvhost_syncpt_init(struct platform_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) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->max_val = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->base_val = kzalloc(sizeof(u32) * nvhost_syncpt_nb_bases(sp),
			GFP_KERNEL);
	sp->lock_counts =
		kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_mlocks(sp),
			GFP_KERNEL);
	sp->caps_nodes = kzalloc(sizeof(struct nvhost_capability_node) * 3,
			GFP_KERNEL);
#if CONFIG_TEGRA_GRHOST_SYNC
	sp->timeline = kzalloc(sizeof(struct nvhost_sync_timeline *) *
			nvhost_syncpt_nb_pts(sp), GFP_KERNEL);
	if (!sp->timeline) {
		err = -ENOMEM;
		goto fail;
	}
#endif

	if (!(sp->min_val && sp->max_val && sp->base_val && sp->lock_counts &&
		sp->caps_nodes)) {
		/* 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;
	}

	sp->caps_kobj = kobject_create_and_add("capabilities", &dev->dev.kobj);
	if (!sp->caps_kobj) {
		err = -EIO;
		goto fail;
	}

	if (nvhost_syncpt_set_sysfs_capability_node(sp, num_syncpts_name,
		sp->caps_nodes, &nvhost_syncpt_nb_pts)) {
		err = -EIO;
		goto fail;
	}

	if (nvhost_syncpt_set_sysfs_capability_node(sp, num_waitbases_name,
		sp->caps_nodes + 1, &nvhost_syncpt_nb_bases)) {
		err = -EIO;
		goto fail;
	}

	if (nvhost_syncpt_set_sysfs_capability_node(sp, num_mutexes_name,
		sp->caps_nodes + 2, &nvhost_syncpt_nb_mlocks)) {
		err = -EIO;
		goto fail;
	}

	/* Allocate two attributes for each sync point: min and max */
	sp->syncpt_attrs = kzalloc(sizeof(*sp->syncpt_attrs)
			* nvhost_syncpt_nb_pts(sp) * 2, GFP_KERNEL);
	if (!sp->syncpt_attrs) {
		err = -ENOMEM;
		goto fail;
	}

	/* Fill in the attributes */
	for (i = 0; i < nvhost_syncpt_nb_pts(sp); i++) {
		struct nvhost_syncpt_attr *min = &sp->syncpt_attrs[i*2];
		struct nvhost_syncpt_attr *max = &sp->syncpt_attrs[i*2+1];

		err = nvhost_syncpt_timeline_attr(host, sp, min, max, i);
		if (err)
			goto fail;

#if CONFIG_TEGRA_GRHOST_SYNC
		sp->timeline[i] = nvhost_sync_timeline_create(sp, i);
		if (!sp->timeline[i]) {
			err = -ENOMEM;
			goto fail;
		}
#endif
	}

	err = nvhost_syncpt_timeline_attr(host, sp, &sp->invalid_min_attr,
					  &sp->invalid_max_attr,
					  NVSYNCPT_INVALID);
	if (err)
		goto fail;

	sp->timeline_invalid = nvhost_sync_timeline_create(sp,
							   NVSYNCPT_INVALID);
	if (!sp->timeline_invalid) {
		err = -ENOMEM;
		goto fail;
	}

	return err;

fail:
	nvhost_syncpt_deinit(sp);
	return err;
}
Exemplo n.º 6
0
int nvhost_syncpt_init(struct platform_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->assigned = kzalloc(sizeof(bool) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->client_managed = kzalloc(sizeof(bool) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->syncpt_names = kzalloc(sizeof(char *) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->min_val = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->max_val = kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_pts(sp),
			GFP_KERNEL);
	sp->base_val = kzalloc(sizeof(u32) * nvhost_syncpt_nb_bases(sp),
			GFP_KERNEL);
	sp->lock_counts =
		kzalloc(sizeof(atomic_t) * nvhost_syncpt_nb_mlocks(sp),
			GFP_KERNEL);
#ifdef CONFIG_TEGRA_GRHOST_SYNC
	sp->timeline = kzalloc(sizeof(struct nvhost_sync_timeline *) *
			nvhost_syncpt_nb_pts(sp), GFP_KERNEL);
	if (!sp->timeline) {
		err = -ENOMEM;
		goto fail;
	}
#endif

	if (!(sp->assigned && sp->client_managed && 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;
	}

	mutex_init(&sp->syncpt_mutex);

	/* Allocate two attributes for each sync point: min and max */
	sp->syncpt_attrs = kzalloc(sizeof(*sp->syncpt_attrs)
			* nvhost_syncpt_nb_pts(sp) * NUM_SYSFS_ENTRY,
			GFP_KERNEL);
	if (!sp->syncpt_attrs) {
		err = -ENOMEM;
		goto fail;
	}

	/* Fill in the attributes */
	for (i = 0; i < nvhost_syncpt_nb_pts(sp); i++) {
		struct nvhost_syncpt_attr *min =
			&sp->syncpt_attrs[i*NUM_SYSFS_ENTRY];
		struct nvhost_syncpt_attr *max =
			&sp->syncpt_attrs[i*NUM_SYSFS_ENTRY+1];
		struct nvhost_syncpt_attr *name =
			&sp->syncpt_attrs[i*NUM_SYSFS_ENTRY+2];
		struct nvhost_syncpt_attr *syncpt_type =
			&sp->syncpt_attrs[i*NUM_SYSFS_ENTRY+3];
		struct nvhost_syncpt_attr *syncpt_assigned =
			&sp->syncpt_attrs[i*NUM_SYSFS_ENTRY+4];

		err = nvhost_syncpt_timeline_attr(host, sp, min, max, name,
					syncpt_type, syncpt_assigned, i);
		if (err)
			goto fail;

		/* initialize syncpt status */
		sp->assigned[i] = false;
		sp->client_managed[i] = false;

#ifdef CONFIG_TEGRA_GRHOST_SYNC
		sp->timeline[i] = nvhost_sync_timeline_create(sp, i);
		if (!sp->timeline[i]) {
			err = -ENOMEM;
			goto fail;
		}
#endif
	}

#ifdef CONFIG_TEGRA_GRHOST_SYNC
	err = nvhost_syncpt_timeline_attr(host, sp, &sp->invalid_min_attr,
					  &sp->invalid_max_attr,
					  &sp->invalid_name_attr,
					  &sp->invalid_syncpt_type_attr,
					  &sp->invalid_assigned_attr,
					  NVSYNCPT_INVALID);
	if (err)
		goto fail;

	sp->timeline_invalid = nvhost_sync_timeline_create(sp,
							   NVSYNCPT_INVALID);
	if (!sp->timeline_invalid) {
		err = -ENOMEM;
		goto fail;
	}
#endif

	/*
	 * some syncpts need to be reserved (hard-coded) because of
	 * external dependencies / constraints
	 */
	nvhost_reserve_syncpts(sp);

	return err;

fail:
	nvhost_syncpt_deinit(sp);
	return err;
}