/* ordered workqueue to process all bulk operations */
struct workqueue_struct *bulk_wq;
+
+ /* Opaque handle for a VCHI instance */
+ VCHI_INSTANCE_T vchi_instance;
};
static struct mmal_msg_context *
mutex_unlock(&instance->vchiq_mutex);
+ vchi_disconnect(instance->vchi_instance);
flush_workqueue(instance->bulk_wq);
destroy_workqueue(instance->bulk_wq);
int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
{
int status;
+ int err = -ENODEV;
struct vchiq_mmal_instance *instance;
static VCHI_INSTANCE_T vchi_instance;
struct service_creation params = {
status = vchi_connect(vchi_instance);
if (status) {
pr_err("Failed to connect VCHI instance (status=%d)\n", status);
- return -EIO;
+ err = -EIO;
+ goto err_disconnect_vchi;
}
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
- if (!instance)
- return -ENOMEM;
+ if (!instance) {
+ err = -ENOMEM;
+ goto err_disconnect_vchi;
+ }
mutex_init(&instance->vchiq_mutex);
instance->bulk_scratch = vmalloc(PAGE_SIZE);
+ instance->vchi_instance = vchi_instance;
mutex_init(&instance->context_map_lock);
idr_init_base(&instance->context_map, 1);
err_free:
vfree(instance->bulk_scratch);
kfree(instance);
- return -ENODEV;
+err_disconnect_vchi:
+ vchi_disconnect(vchi_instance);
+ return err;
}
EXPORT_SYMBOL_GPL(vchiq_mmal_init);