@@ -187,21 +187,32 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
{
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
if (dvbdev->entity) {
+ media_device_unregister_entity(dvbdev->entity);
+ kfree(dvbdev->entity);
+ kfree(dvbdev->pads);
+ dvbdev->entity = NULL;
+ dvbdev->pads = NULL;
+ }
+
+ if (dvbdev->tsout_entity) {
int i;
for (i = 0; i < dvbdev->tsout_num_entities; i++) {
media_device_unregister_entity(&dvbdev->tsout_entity[i]);
kfree(dvbdev->tsout_entity[i].name);
}
- media_device_unregister_entity(dvbdev->entity);
-
- kfree(dvbdev->entity);
- kfree(dvbdev->pads);
kfree(dvbdev->tsout_entity);
kfree(dvbdev->tsout_pads);
+ dvbdev->tsout_entity = NULL;
+ dvbdev->tsout_pads = NULL;
+
+ dvbdev->tsout_num_entities = 0;
}
- if (dvbdev->intf_devnode)
+
+ if (dvbdev->intf_devnode) {
media_devnode_remove(dvbdev->intf_devnode);
+ dvbdev->intf_devnode = NULL;
+ }
#endif
}
@@ -221,13 +232,15 @@ static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
if (!dvbdev->tsout_entity)
return -ENOMEM;
+ dvbdev->tsout_num_entities = npads;
+
for (i = 0; i < npads; i++) {
struct media_pad *pads = &dvbdev->tsout_pads[i];
struct media_entity *entity = &dvbdev->tsout_entity[i];
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
if (!entity->name)
- return ret;
+ return -ENOMEM;
entity->type = MEDIA_ENT_T_DVB_TSOUT;
pads->flags = MEDIA_PAD_FL_SINK;
@@ -318,9 +331,11 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
break;
default:
+ /* Should never happen, as the first switch prevents it */
kfree(dvbdev->entity);
kfree(dvbdev->pads);
dvbdev->entity = NULL;
+ dvbdev->pads = NULL;
return 0;
}
@@ -423,24 +438,13 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
return -ENFILE;
}
- *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
+ *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
if (!dvbdev){
mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
- ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
- if (ret) {
- printk(KERN_ERR
- "%s: dvb_register_media_device failed to create the mediagraph\n",
- __func__);
-
- dvb_media_device_free(dvbdev);
- mutex_unlock(&dvbdev_register_lock);
- return ret;
- }
-
dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
if (!dvbdevfops){
@@ -483,6 +487,20 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
dvb_minors[minor] = dvbdev;
up_write(&minor_rwsem);
+ ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: dvb_register_media_device failed to create the mediagraph\n",
+ __func__);
+
+ dvb_media_device_free(dvbdev);
+ kfree(dvbdevfops);
+ kfree(dvbdev);
+ up_write(&minor_rwsem);
+ mutex_unlock(&dvbdev_register_lock);
+ return ret;
+ }
+
mutex_unlock(&dvbdev_register_lock);
clsdev = device_create(dvb_class, adap->device,
@@ -576,6 +576,10 @@ void media_device_unregister(struct media_device *mdev)
struct media_entity *next;
struct media_interface *intf, *tmp_intf;
+ /* Remove all entities from the media device */
+ list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
+ media_device_unregister_entity(entity);
+
/* Remove all interfaces from the media device */
spin_lock(&mdev->lock);
list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
@@ -586,9 +590,6 @@ void media_device_unregister(struct media_device *mdev)
}
spin_unlock(&mdev->lock);
- list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
- media_device_unregister_entity(entity);
-
device_remove_file(&mdev->devnode.dev, &dev_attr_model);
media_devnode_unregister(&mdev->devnode);
@@ -654,8 +655,7 @@ void media_device_unregister_entity(struct media_entity *entity)
/* Remove all interface links pointing to this entity */
list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) {
list_for_each_entry_safe(link, tmp, &intf->links, list) {
- if (media_type(link->gobj1) == MEDIA_GRAPH_ENTITY
- && link->entity == entity)
+ if (link->entity == entity)
__media_remove_intf_link(link);
}
}