The vchi_instance is allocated with vchiq_initialise() but never
handled properly. Fix memory leak for the vchi_instance.
This fixes below kmemleak report:
[<
000000002312557f>] kmem_cache_alloc_trace+0x1e0/0x348
[<
000000002ee5d470>] vchiq_initialise+0xd0/0x258
[<
000000009b51d8f4>] vchi_initialise+0x84/0xc8
[<
00000000a58f68c5>] vchiq_mmal_init+0xb0/0x2f0
[<
000000006c68d7bf>] bcm2835_mmal_probe+0x90/0x660
...
Change-Id: Ib10f194aa4058b3e39ec0a250fa36fd00daf9feb
Reported-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
/* ordered workqueue to process all bulk operations */
struct workqueue_struct *bulk_wq;
/* 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 *
};
static struct mmal_msg_context *
mutex_unlock(&instance->vchiq_mutex);
mutex_unlock(&instance->vchiq_mutex);
+ vchi_disconnect(instance->vchi_instance);
flush_workqueue(instance->bulk_wq);
destroy_workqueue(instance->bulk_wq);
flush_workqueue(instance->bulk_wq);
destroy_workqueue(instance->bulk_wq);
int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
{
int status;
int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
{
int status;
struct vchiq_mmal_instance *instance;
static VCHI_INSTANCE_T vchi_instance;
struct service_creation params = {
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);
status = vchi_connect(vchi_instance);
if (status) {
pr_err("Failed to connect VCHI instance (status=%d)\n", status);
+ err = -EIO;
+ goto err_disconnect_vchi;
}
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
}
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);
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);
mutex_init(&instance->context_map_lock);
idr_init_base(&instance->context_map, 1);
err_free:
vfree(instance->bulk_scratch);
kfree(instance);
err_free:
vfree(instance->bulk_scratch);
kfree(instance);
+err_disconnect_vchi:
+ vchi_disconnect(vchi_instance);
+ return err;
}
EXPORT_SYMBOL_GPL(vchiq_mmal_init);
}
EXPORT_SYMBOL_GPL(vchiq_mmal_init);