Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e43f3fab authored by Darron Broad's avatar Darron Broad Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (9266): videobuf: properly handle attachment failure



This fixes attachment failure where we now unwind
attachment and skip non-attached nodes where
necessary so we can survive a fault situation
correctly.

Signed-off-by: default avatarDarron Broad <darron@kewl.org>
Signed-off-by: default avatarSteven Toth <stoth@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 7bdf84fc
Loading
Loading
Loading
Loading
+24 −13
Original line number Diff line number Diff line
@@ -145,19 +145,19 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
{
	struct list_head *list, *q;
	struct videobuf_dvb_frontend *fe;
	int res = -EINVAL;
	int res;

	fe = videobuf_dvb_get_frontend(f, 1);
	if (!fe) {
		printk(KERN_WARNING "Unable to register the adapter which has no frontends\n");
		goto err;
		return -EINVAL;
	}

	/* Bring up the adapter */
	res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr, mfe_shared);
	if (res < 0) {
		printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
		goto err;
		return res;
	}

	/* Attach all of the frontends to the adapter */
@@ -168,11 +168,15 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
		if (res < 0) {
			printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n",
				fe->dvb.name, res);
			goto err;
		}
	}
	mutex_unlock(&f->lock);
	return 0;

err:
	mutex_unlock(&f->lock);
	videobuf_dvb_unregister_bus(f);
	return res;
}

@@ -264,6 +268,10 @@ int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_

	/* register network adapter */
	dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
	if (dvb->net.dvbdev == NULL) {
		result = -ENOMEM;
		goto fail_fe_conn;
	}
	return 0;

fail_fe_conn:
@@ -278,7 +286,7 @@ int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_
	dvb_unregister_frontend(dvb->frontend);
fail_frontend:
	dvb_frontend_detach(dvb->frontend);
	dvb_unregister_adapter(adapter);
	dvb->frontend = NULL;

	return result;
}
@@ -291,15 +299,18 @@ void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
	mutex_lock(&f->lock);
	list_for_each_safe(list, q, &f->felist) {
		fe = list_entry(list, struct videobuf_dvb_frontend, felist);

		if(fe->dvb.net.dvbdev) {
			dvb_net_release(&fe->dvb.net);
			fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_mem);
			fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_hw);
			dvb_dmxdev_release(&fe->dvb.dmxdev);
			dvb_dmx_release(&fe->dvb.demux);
			dvb_unregister_frontend(fe->dvb.frontend);
		}
		if(fe->dvb.frontend) {	/* always allocated, may have been reset */
			dvb_frontend_detach(fe->dvb.frontend);

			fe->dvb.frontend = NULL;
		}
		list_del(list);
		kfree(fe);
	}