{
struct nvkm_engine *engine = *pengine;
if (engine) {
- mutex_lock(&engine->subdev.mutex);
- if (--engine->usecount == 0)
+ if (refcount_dec_and_mutex_lock(&engine->use.refcount, &engine->use.mutex)) {
nvkm_subdev_fini(&engine->subdev, false);
- mutex_unlock(&engine->subdev.mutex);
+ engine->use.enabled = false;
+ mutex_unlock(&engine->use.mutex);
+ }
*pengine = NULL;
}
}
struct nvkm_engine *
nvkm_engine_ref(struct nvkm_engine *engine)
{
+ int ret;
if (engine) {
- mutex_lock(&engine->subdev.mutex);
- if (++engine->usecount == 1) {
- int ret = nvkm_subdev_init(&engine->subdev);
- if (ret) {
- engine->usecount--;
- mutex_unlock(&engine->subdev.mutex);
- return ERR_PTR(ret);
+ if (!refcount_inc_not_zero(&engine->use.refcount)) {
+ mutex_lock(&engine->use.mutex);
+ if (!refcount_inc_not_zero(&engine->use.refcount)) {
+ engine->use.enabled = true;
+ if ((ret = nvkm_subdev_init(&engine->subdev))) {
+ engine->use.enabled = false;
+ mutex_unlock(&engine->use.mutex);
+ return ERR_PTR(ret);
+ }
+ refcount_set(&engine->use.refcount, 1);
}
+ mutex_unlock(&engine->use.mutex);
}
- mutex_unlock(&engine->subdev.mutex);
}
return engine;
}
int ret = 0, i;
s64 time;
- if (!engine->usecount) {
+ if (!engine->use.enabled) {
nvkm_trace(subdev, "init skipped, engine has no users\n");
return ret;
}
struct nvkm_engine *engine = nvkm_engine(subdev);
if (engine->func->dtor)
return engine->func->dtor(engine);
+ mutex_destroy(&engine->use.mutex);
return engine;
}
{
nvkm_subdev_ctor(&nvkm_engine_func, device, index, &engine->subdev);
engine->func = func;
+ refcount_set(&engine->use.refcount, 0);
+ mutex_init(&engine->use.mutex);
if (!nvkm_boolopt(device->cfgopt, nvkm_subdev_name[index], enable)) {
nvkm_debug(&engine->subdev, "disabled\n");