#include "vipx-context.h"
#include "vipx-core.h"
-static inline int __vref_get(struct vipx_core_refcount *vref)
-{
- int ret;
-
- vipx_enter();
- ret = (atomic_inc_return(&vref->refcount) == 1) ?
- vref->first(vref->core) : 0;
- if (ret)
- atomic_dec(&vref->refcount);
- vipx_leave();
- return ret;
-}
-
-static inline int __vref_put(struct vipx_core_refcount *vref)
-{
- int ret;
-
- vipx_enter();
- ret = (atomic_dec_return(&vref->refcount) == 0) ?
- vref->final(vref->core) : 0;
- if (ret)
- atomic_inc(&vref->refcount);
- vipx_leave();
- return ret;
-}
-
static int vipx_core_set_graph(struct vipx_context *vctx,
struct vs4l_graph *ginfo)
{
static int vipx_core_streamon(struct vipx_context *vctx)
{
int ret;
- struct vipx_core *core;
+ struct vipx_device *vdev;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
goto p_err_state;
}
- core = vctx->core;
- ret = __vref_get(&core->start_cnt);
- if (ret) {
- vipx_err("vref_get(start) is fail(%d)\n", ret);
- goto p_err_vref;
- }
+ vdev = vctx->core->device;
+ ret = vipx_device_start(vdev);
+ if (ret)
+ goto p_err_start;
ret = vctx->queue_ops->streamon(&vctx->queue_list);
if (ret)
vipx_leave();
return 0;
p_err_queue_ops:
-p_err_vref:
+ vipx_device_stop(vdev);
+p_err_start:
p_err_state:
mutex_unlock(&vctx->lock);
p_err_lock:
static int vipx_core_streamoff(struct vipx_context *vctx)
{
int ret;
- struct vipx_core *core;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
if (ret)
goto p_err_queue_ops;
- core = vctx->core;
- ret = __vref_put(&core->start_cnt);
- if (ret) {
- vipx_err("vref_put(start) is fail(%d)\n", ret);
- goto p_err_vref;
- }
+ vipx_device_stop(vctx->core->device);
vctx->state = BIT(VIPX_CONTEXT_STOP);
mutex_unlock(&vctx->lock);
vipx_leave();
return 0;
-p_err_vref:
p_err_queue_ops:
p_err_state:
mutex_unlock(&vctx->lock);
{
int ret;
struct miscdevice *miscdev;
- struct vipx_device *device;
+ struct vipx_device *vdev;
struct vipx_core *core;
struct vipx_context *vctx;
struct vipx_graph *graph;
vipx_enter();
miscdev = file->private_data;
- device = dev_get_drvdata(miscdev->parent);
- core = &device->core;
+ vdev = dev_get_drvdata(miscdev->parent);
+ core = &vdev->core;
if (mutex_lock_interruptible(&core->lock)) {
ret = -ERESTARTSYS;
goto p_err_lock;
}
- ret = __vref_get(&core->open_cnt);
- if (ret) {
- vipx_err("vref_get(open) is fail(%d)", ret);
- goto p_err_vref;
- }
+ ret = vipx_device_open(vdev);
+ if (ret)
+ goto p_err_device;
vctx = vipx_context_create(core);
if (IS_ERR(vctx)) {
return 0;
p_err_graph:
p_err_vctx:
- __vref_put(&core->open_cnt);
-p_err_vref:
+ vipx_device_close(vdev);
+p_err_device:
mutex_unlock(&core->lock);
vipx_err("Failed to open the vipx [%d]\n", ret);
p_err_lock:
vipx_graph_destroy(vctx->graph);
vipx_context_destroy(vctx);
- __vref_put(&core->open_cnt);
+ vipx_device_close(core->device);
mutex_unlock(&core->lock);
vipx_info("The vipx has been closed\n");
.compat_ioctl = vipx_compat_ioctl
};
-static int __vref_open(struct vipx_core *core)
-{
- vipx_check();
- atomic_set(&core->start_cnt.refcount, 0);
- return vipx_device_open(core->device);
-}
-
-static int __vref_close(struct vipx_core *core)
-{
- vipx_check();
- return vipx_device_close(core->device);
-}
-
-static int __vref_start(struct vipx_core *core)
-{
- vipx_check();
- return vipx_device_start(core->device);
-}
-
-static int __vref_stop(struct vipx_core *core)
-{
- vipx_check();
- return vipx_device_stop(core->device);
-}
-
-static inline void __vref_init(struct vipx_core_refcount *vref,
- struct vipx_core *core,
- int (*first)(struct vipx_core *core),
- int (*final)(struct vipx_core *core))
-{
- vipx_enter();
- vref->core = core;
- vref->first = first;
- vref->final = final;
- atomic_set(&vref->refcount, 0);
- vipx_leave();
-}
-
/* Top-level data for debugging */
-static struct vipx_dev *vdev;
+static struct vipx_miscdev *misc_vdev;
-int vipx_core_probe(struct vipx_device *device)
+int vipx_core_probe(struct vipx_device *vdev)
{
int ret;
struct vipx_core *core;
vipx_enter();
- core = &device->core;
- core->device = device;
- core->system = &device->system;
- vdev = &core->vdev;
+ core = &vdev->core;
+ core->device = vdev;
+ core->system = &vdev->system;
+ misc_vdev = &core->misc_vdev;
mutex_init(&core->lock);
- __vref_init(&core->open_cnt, core, __vref_open, __vref_close);
- __vref_init(&core->start_cnt, core, __vref_start, __vref_stop);
core->ioc_ops = &vipx_core_ioctl_ops;
vipx_util_bitmap_init(core->vctx_map, VIPX_MAX_CONTEXT);
INIT_LIST_HEAD(&core->vctx_list);
core->vctx_count = 0;
- vdev->miscdev.minor = MISC_DYNAMIC_MINOR;
- vdev->miscdev.name = VIPX_DEV_NAME;
- vdev->miscdev.fops = &vipx_file_ops;
- vdev->miscdev.parent = device->dev;
+ core->misc_vdev.miscdev.minor = MISC_DYNAMIC_MINOR;
+ core->misc_vdev.miscdev.name = VIPX_DEV_NAME;
+ core->misc_vdev.miscdev.fops = &vipx_file_ops;
+ core->misc_vdev.miscdev.parent = vdev->dev;
- ret = misc_register(&vdev->miscdev);
+ ret = misc_register(&core->misc_vdev.miscdev);
if (ret) {
vipx_err("miscdevice is not registered (%d)\n", ret);
goto p_err_misc;
void vipx_core_remove(struct vipx_core *core)
{
vipx_enter();
- misc_deregister(&core->vdev.miscdev);
+ misc_deregister(&core->misc_vdev.miscdev);
mutex_destroy(&core->lock);
vipx_leave();
}
#include "vipx-graph.h"
#include "vipx-device.h"
-void __vipx_fault_handler(struct vipx_device *device)
+static void __vipx_fault_handler(struct vipx_device *vdev)
{
vipx_enter();
vipx_leave();
struct iommu_domain *domain, struct device *dev,
unsigned long fault_addr, int fault_flag, void *token)
{
- struct vipx_device *device;
+ struct vipx_device *vdev;
pr_err("< VIPX FAULT HANDLER >\n");
pr_err("Device virtual(0x%lX) is invalid access\n", fault_addr);
- device = dev_get_drvdata(dev);
+ vdev = dev_get_drvdata(dev);
vipx_debug_dump_debug_regs();
- __vipx_fault_handler(device);
+ __vipx_fault_handler(vdev);
return -EINVAL;
}
+static int __vipx_device_start(struct vipx_device *vdev)
+{
+ int ret;
+
+ vipx_enter();
+ ret = vipx_system_start(&vdev->system);
+ if (ret)
+ goto p_err_system;
+
+ ret = vipx_debug_start(&vdev->debug);
+ if (ret)
+ goto p_err_debug;
+
+ vipx_leave();
+ return 0;
+p_err_debug:
+ vipx_system_stop(&vdev->system);
+p_err_system:
+ return ret;
+}
+
+static int __vipx_device_stop(struct vipx_device *vdev)
+{
+ vipx_enter();
+ vipx_debug_stop(&vdev->debug);
+ vipx_system_stop(&vdev->system);
+ vipx_leave();
+ return 0;
+}
+
#if defined(CONFIG_PM_SLEEP)
static int vipx_device_suspend(struct device *dev)
{
+ int ret;
+ struct vipx_device *vdev;
+
vipx_enter();
+ vdev = dev_get_drvdata(dev);
+
+ mutex_lock(&vdev->open_lock);
+ if (!vdev->open_count) {
+ vipx_warn("device is already closed\n");
+ mutex_unlock(&vdev->open_lock);
+ return 0;
+ }
+
+ mutex_lock(&vdev->start_lock);
+ vdev->suspended = true;
+ if (vdev->start_count)
+ __vipx_device_stop(vdev);
+ mutex_unlock(&vdev->start_lock);
+
+ ret = vipx_system_suspend(&vdev->system);
+ if (ret)
+ goto p_err;
+
vipx_leave();
- return 0;
+p_err:
+ mutex_unlock(&vdev->open_lock);
+ return ret;
}
static int vipx_device_resume(struct device *dev)
{
+ int ret;
+ struct vipx_device *vdev;
+
vipx_enter();
+ vdev = dev_get_drvdata(dev);
+
+ mutex_lock(&vdev->open_lock);
+ if (!vdev->open_count) {
+ vipx_warn("device is already closed\n");
+ mutex_unlock(&vdev->open_lock);
+ return 0;
+ }
+
+ ret = vipx_system_resume(&vdev->system);
+ if (ret)
+ goto p_err;
+
+ mutex_lock(&vdev->start_lock);
+ vdev->suspended = false;
+ if (vdev->start_count)
+ __vipx_device_start(vdev);
+ mutex_unlock(&vdev->start_lock);
+
vipx_leave();
- return 0;
+p_err:
+ mutex_unlock(&vdev->open_lock);
+ return ret;
}
#endif
static int vipx_device_runtime_suspend(struct device *dev)
{
int ret;
- struct vipx_device *device;
+ struct vipx_device *vdev;
vipx_enter();
- device = dev_get_drvdata(dev);
+ vdev = dev_get_drvdata(dev);
- ret = vipx_system_runtime_suspend(&device->system);
+ ret = vipx_system_runtime_suspend(&vdev->system);
if (ret)
goto p_err;
static int vipx_device_runtime_resume(struct device *dev)
{
int ret;
- struct vipx_device *device;
+ struct vipx_device *vdev;
vipx_enter();
- device = dev_get_drvdata(dev);
+ vdev = dev_get_drvdata(dev);
- ret = vipx_system_runtime_resume(&device->system);
+ ret = vipx_system_runtime_resume(&vdev->system);
if (ret)
goto p_err;
NULL)
};
-static int __vipx_device_start(struct vipx_device *device)
+int vipx_device_start(struct vipx_device *vdev)
{
int ret;
vipx_enter();
- if (!test_bit(VIPX_DEVICE_STATE_OPEN, &device->state)) {
- ret = -EINVAL;
- vipx_err("device was not opend yet (%lx)\n", device->state);
- goto p_err_state;
+ mutex_lock(&vdev->start_lock);
+ if (vdev->suspended) {
+ ret = -ENOSTR;
+ vipx_err("Failed to start device as it was suspended(%d)\n",
+ ret);
+ goto p_err;
}
- if (test_bit(VIPX_DEVICE_STATE_START, &device->state))
+ if (vdev->start_count) {
+ vdev->start_count++;
+ mutex_unlock(&vdev->start_lock);
return 0;
+ }
- ret = vipx_system_start(&device->system);
- if (ret)
- goto p_err_system;
-
- ret = vipx_debug_start(&device->debug);
+ ret = __vipx_device_start(vdev);
if (ret)
- goto p_err_debug;
-
- set_bit(VIPX_DEVICE_STATE_START, &device->state);
+ goto p_err;
+ vdev->start_count = 1;
vipx_leave();
- return 0;
-p_err_debug:
- vipx_system_stop(&device->system);
-p_err_system:
-p_err_state:
+p_err:
+ mutex_unlock(&vdev->start_lock);
return ret;
}
-static int __vipx_device_stop(struct vipx_device *device)
+int vipx_device_stop(struct vipx_device *vdev)
{
vipx_enter();
- if (!test_bit(VIPX_DEVICE_STATE_START, &device->state))
- return 0;
-
- vipx_debug_stop(&device->debug);
- vipx_system_stop(&device->system);
- clear_bit(VIPX_DEVICE_STATE_START, &device->state);
-
+ mutex_lock(&vdev->start_lock);
+ if (!(--vdev->start_count) && !vdev->suspended)
+ __vipx_device_stop(vdev);
+ mutex_unlock(&vdev->start_lock);
vipx_leave();
return 0;
}
-static int __vipx_device_power_on(struct vipx_device *device)
+static int __vipx_device_power_on(struct vipx_device *vdev)
{
int ret;
vipx_enter();
#if defined(CONFIG_PM)
- ret = pm_runtime_get_sync(device->dev);
+ ret = pm_runtime_get_sync(vdev->dev);
if (ret) {
vipx_err("Failed to get pm_runtime sync (%d)\n", ret);
goto p_err;
}
#else
- ret = vipx_device_runtime_resume(device->dev);
+ ret = vipx_device_runtime_resume(vdev->dev);
if (ret)
goto p_err;
#endif
return ret;
}
-static int __vipx_device_power_off(struct vipx_device *device)
+static int __vipx_device_power_off(struct vipx_device *vdev)
{
int ret;
vipx_enter();
#if defined(CONFIG_PM)
- ret = pm_runtime_put_sync(device->dev);
+ ret = pm_runtime_put_sync(vdev->dev);
if (ret) {
vipx_err("Failed to put pm_runtime sync (%d)\n", ret);
goto p_err;
}
#else
- ret = vipx_device_runtime_suspend(device->dev);
+ ret = vipx_device_runtime_suspend(vdev->dev);
if (ret)
goto p_err;
#endif
return ret;
}
-int vipx_device_start(struct vipx_device *device)
-{
- int ret;
-
- vipx_enter();
- ret = __vipx_device_start(device);
- if (ret)
- goto p_err;
-
- vipx_leave();
-p_err:
- return ret;
-}
-
-int vipx_device_stop(struct vipx_device *device)
-{
- int ret;
-
- vipx_enter();
- ret = __vipx_device_stop(device);
- if (ret)
- goto p_err;
-
- vipx_leave();
-p_err:
- return ret;
-}
-
-int vipx_device_open(struct vipx_device *device)
+int vipx_device_open(struct vipx_device *vdev)
{
int ret;
vipx_enter();
- if (test_bit(VIPX_DEVICE_STATE_OPEN, &device->state)) {
- ret = -EINVAL;
- vipx_warn("device was already opened\n");
- goto p_err_state;
+ mutex_lock(&vdev->open_lock);
+ if (vdev->open_count) {
+ vdev->open_count++;
+ mutex_unlock(&vdev->open_lock);
+ return 0;
}
- ret = vipx_system_open(&device->system);
+ ret = vipx_system_open(&vdev->system);
if (ret)
goto p_err_system;
- ret = vipx_debug_open(&device->debug);
+ ret = vipx_debug_open(&vdev->debug);
if (ret)
goto p_err_debug;
- ret = __vipx_device_power_on(device);
+ ret = __vipx_device_power_on(vdev);
if (ret)
goto p_err_power;
- ret = vipx_system_fw_bootup(&device->system);
+ ret = vipx_system_fw_bootup(&vdev->system);
if (ret)
goto p_err_boot;
- set_bit(VIPX_DEVICE_STATE_OPEN, &device->state);
+ vdev->open_count = 1;
+ mutex_lock(&vdev->start_lock);
+ vdev->start_count = 0;
+ vdev->suspended = false;
+ mutex_unlock(&vdev->start_lock);
+ mutex_unlock(&vdev->open_lock);
vipx_leave();
return 0;
p_err_boot:
- __vipx_device_power_off(device);
+ __vipx_device_power_off(vdev);
p_err_power:
- vipx_debug_close(&device->debug);
+ vipx_debug_close(&vdev->debug);
p_err_debug:
- vipx_system_close(&device->system);
+ vipx_system_close(&vdev->system);
p_err_system:
-p_err_state:
+ mutex_unlock(&vdev->open_lock);
return ret;
}
-int vipx_device_close(struct vipx_device *device)
+int vipx_device_close(struct vipx_device *vdev)
{
vipx_enter();
- if (!test_bit(VIPX_DEVICE_STATE_OPEN, &device->state)) {
+ mutex_lock(&vdev->open_lock);
+ if (!vdev->open_count) {
vipx_warn("device is already closed\n");
- goto p_err;
+ goto p_end;
}
- if (test_bit(VIPX_DEVICE_STATE_START, &device->state))
- __vipx_device_stop(device);
-
- __vipx_device_power_off(device);
- vipx_debug_close(&device->debug);
- vipx_system_close(&device->system);
- clear_bit(VIPX_DEVICE_STATE_OPEN, &device->state);
+ if (!(--vdev->open_count)) {
+ mutex_lock(&vdev->start_lock);
+ if (vdev->start_count) {
+ __vipx_device_stop(vdev);
+ vdev->start_count = 0;
+ }
+ mutex_unlock(&vdev->start_lock);
+
+ __vipx_device_power_off(vdev);
+ vipx_debug_close(&vdev->debug);
+ vipx_system_close(&vdev->system);
+ }
vipx_leave();
-p_err:
+p_end:
+ mutex_unlock(&vdev->open_lock);
return 0;
}
{
int ret;
struct device *dev;
- struct vipx_device *device;
+ struct vipx_device *vdev;
vipx_enter();
dev = &pdev->dev;
- device = devm_kzalloc(dev, sizeof(*device), GFP_KERNEL);
- if (!device) {
+ vdev = devm_kzalloc(dev, sizeof(*vdev), GFP_KERNEL);
+ if (!vdev) {
ret = -ENOMEM;
vipx_err("Fail to alloc device structure\n");
goto p_err_alloc;
}
get_device(dev);
- device->dev = dev;
- dev_set_drvdata(dev, device);
+ vdev->dev = dev;
+ dev_set_drvdata(dev, vdev);
+
+ mutex_init(&vdev->open_lock);
+ vdev->open_count = 0;
+ mutex_init(&vdev->start_lock);
+ vdev->start_count = 0;
- ret = vipx_system_probe(device);
+ ret = vipx_system_probe(vdev);
if (ret)
goto p_err_system;
- ret = vipx_core_probe(device);
+ ret = vipx_core_probe(vdev);
if (ret)
goto p_err_core;
- ret = vipx_debug_probe(device);
+ ret = vipx_debug_probe(vdev);
if (ret)
goto p_err_debug;
vipx_info("vipx device is initilized\n");
return 0;
p_err_debug:
- vipx_core_remove(&device->core);
+ vipx_core_remove(&vdev->core);
p_err_core:
- vipx_system_remove(&device->system);
+ vipx_system_remove(&vdev->system);
p_err_system:
- devm_kfree(dev, device);
+ devm_kfree(dev, vdev);
p_err_alloc:
vipx_err("vipx device is not registered (%d)\n", ret);
return ret;
static int vipx_device_remove(struct platform_device *pdev)
{
- struct vipx_device *device;
+ struct vipx_device *vdev;
vipx_enter();
- device = dev_get_drvdata(&pdev->dev);
+ vdev = dev_get_drvdata(&pdev->dev);
- vipx_debug_remove(&device->debug);
- vipx_core_remove(&device->core);
- vipx_system_remove(&device->system);
- devm_kfree(device->dev, device);
+ vipx_debug_remove(&vdev->debug);
+ vipx_core_remove(&vdev->core);
+ vipx_system_remove(&vdev->system);
+ devm_kfree(vdev->dev, vdev);
vipx_leave();
return 0;
}
static void vipx_device_shutdown(struct platform_device *pdev)
{
- struct vipx_device *device;
+ struct vipx_device *vdev;
vipx_enter();
- device = dev_get_drvdata(&pdev->dev);
+ vdev = dev_get_drvdata(&pdev->dev);
vipx_leave();
}