aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorDarron Broad <darron@kewl.org>2008-10-15 12:48:43 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-17 16:28:41 -0400
commite43f3fab0514647e563ee8b5baf4ce100dd5caa5 (patch)
tree93d8088eb167d8d76ea06a7e66c5c44f0546c2fa /drivers/media
parent7bdf84fc47f2d2ed2194b6ade480d043207c4098 (diff)
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: Darron Broad <darron@kewl.org> Signed-off-by: Steven Toth <stoth@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/videobuf-dvb.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index fc4cfaa7bf5f..7c74845af267 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -145,19 +145,19 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
145{ 145{
146 struct list_head *list, *q; 146 struct list_head *list, *q;
147 struct videobuf_dvb_frontend *fe; 147 struct videobuf_dvb_frontend *fe;
148 int res = -EINVAL; 148 int res;
149 149
150 fe = videobuf_dvb_get_frontend(f, 1); 150 fe = videobuf_dvb_get_frontend(f, 1);
151 if (!fe) { 151 if (!fe) {
152 printk(KERN_WARNING "Unable to register the adapter which has no frontends\n"); 152 printk(KERN_WARNING "Unable to register the adapter which has no frontends\n");
153 goto err; 153 return -EINVAL;
154 } 154 }
155 155
156 /* Bring up the adapter */ 156 /* Bring up the adapter */
157 res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr, mfe_shared); 157 res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr, mfe_shared);
158 if (res < 0) { 158 if (res < 0) {
159 printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); 159 printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
160 goto err; 160 return res;
161 } 161 }
162 162
163 /* Attach all of the frontends to the adapter */ 163 /* Attach all of the frontends to the adapter */
@@ -168,11 +168,15 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
168 if (res < 0) { 168 if (res < 0) {
169 printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n", 169 printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n",
170 fe->dvb.name, res); 170 fe->dvb.name, res);
171 goto err;
171 } 172 }
172 } 173 }
173 mutex_unlock(&f->lock); 174 mutex_unlock(&f->lock);
175 return 0;
174 176
175err: 177err:
178 mutex_unlock(&f->lock);
179 videobuf_dvb_unregister_bus(f);
176 return res; 180 return res;
177} 181}
178 182
@@ -264,6 +268,10 @@ int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_
264 268
265 /* register network adapter */ 269 /* register network adapter */
266 dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx); 270 dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
271 if (dvb->net.dvbdev == NULL) {
272 result = -ENOMEM;
273 goto fail_fe_conn;
274 }
267 return 0; 275 return 0;
268 276
269fail_fe_conn: 277fail_fe_conn:
@@ -278,7 +286,7 @@ fail_dmx:
278 dvb_unregister_frontend(dvb->frontend); 286 dvb_unregister_frontend(dvb->frontend);
279fail_frontend: 287fail_frontend:
280 dvb_frontend_detach(dvb->frontend); 288 dvb_frontend_detach(dvb->frontend);
281 dvb_unregister_adapter(adapter); 289 dvb->frontend = NULL;
282 290
283 return result; 291 return result;
284} 292}
@@ -291,15 +299,18 @@ void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
291 mutex_lock(&f->lock); 299 mutex_lock(&f->lock);
292 list_for_each_safe(list, q, &f->felist) { 300 list_for_each_safe(list, q, &f->felist) {
293 fe = list_entry(list, struct videobuf_dvb_frontend, felist); 301 fe = list_entry(list, struct videobuf_dvb_frontend, felist);
294 302 if(fe->dvb.net.dvbdev) {
295 dvb_net_release(&fe->dvb.net); 303 dvb_net_release(&fe->dvb.net);
296 fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_mem); 304 fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_mem);
297 fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_hw); 305 fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_hw);
298 dvb_dmxdev_release(&fe->dvb.dmxdev); 306 dvb_dmxdev_release(&fe->dvb.dmxdev);
299 dvb_dmx_release(&fe->dvb.demux); 307 dvb_dmx_release(&fe->dvb.demux);
300 dvb_unregister_frontend(fe->dvb.frontend); 308 dvb_unregister_frontend(fe->dvb.frontend);
301 dvb_frontend_detach(fe->dvb.frontend); 309 }
302 310 if(fe->dvb.frontend) { /* always allocated, may have been reset */
311 dvb_frontend_detach(fe->dvb.frontend);
312 fe->dvb.frontend = NULL;
313 }
303 list_del(list); 314 list_del(list);
304 kfree(fe); 315 kfree(fe);
305 } 316 }