return err;
 }
 
-static void zr364xx_release(struct v4l2_device *v4l2_dev)
+static void zr364xx_board_uninit(struct zr364xx_camera *cam)
 {
-       struct zr364xx_camera *cam =
-               container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
        unsigned long i;
 
-       v4l2_device_unregister(&cam->v4l2_dev);
-
-       videobuf_mmap_free(&cam->vb_vidq);
+       zr364xx_stop_readpipe(cam);
 
        /* release sys buffers */
        for (i = 0; i < FRAMES; i++) {
                cam->buffer.frame[i].lpvbits = NULL;
        }
 
-       v4l2_ctrl_handler_free(&cam->ctrl_handler);
        /* release transfer buffer */
        kfree(cam->pipe->transfer_buffer);
+}
+
+static void zr364xx_release(struct v4l2_device *v4l2_dev)
+{
+       struct zr364xx_camera *cam =
+               container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
+
+       videobuf_mmap_free(&cam->vb_vidq);
+       v4l2_ctrl_handler_free(&cam->ctrl_handler);
+       zr364xx_board_uninit(cam);
+       v4l2_device_unregister(&cam->v4l2_dev);
        kfree(cam);
 }
 
        /* start read pipe */
        err = zr364xx_start_readpipe(cam);
        if (err)
-               goto err_free;
+               goto err_free_frames;
 
        DBG(": board initialized\n");
        return 0;
 
+err_free_frames:
+       for (i = 0; i < FRAMES; i++)
+               vfree(cam->buffer.frame[i].lpvbits);
 err_free:
        kfree(cam->pipe->transfer_buffer);
        cam->pipe->transfer_buffer = NULL;
        if (!cam)
                return -ENOMEM;
 
-       cam->v4l2_dev.release = zr364xx_release;
        err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
        if (err < 0) {
                dev_err(&udev->dev, "couldn't register v4l2_device\n");
-               kfree(cam);
-               return err;
+               goto free_cam;
        }
        hdl = &cam->ctrl_handler;
        v4l2_ctrl_handler_init(hdl, 1);
        if (hdl->error) {
                err = hdl->error;
                dev_err(&udev->dev, "couldn't register control\n");
-               goto fail;
+               goto unregister;
        }
        /* save the init method used by this camera */
        cam->method = id->driver_info;
        if (!cam->read_endpoint) {
                err = -ENOMEM;
                dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
-               goto fail;
+               goto unregister;
        }
 
        /* v4l */
 
        /* load zr364xx board specific */
        err = zr364xx_board_init(cam);
-       if (!err)
-               err = v4l2_ctrl_handler_setup(hdl);
        if (err)
-               goto fail;
+               goto unregister;
+       err = v4l2_ctrl_handler_setup(hdl);
+       if (err)
+               goto board_uninit;
 
        spin_lock_init(&cam->slock);
 
        err = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1);
        if (err) {
                dev_err(&udev->dev, "video_register_device failed\n");
-               goto fail;
+               goto free_handler;
        }
+       cam->v4l2_dev.release = zr364xx_release;
 
        dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
                 video_device_node_name(&cam->vdev));
        return 0;
 
-fail:
+free_handler:
        v4l2_ctrl_handler_free(hdl);
+board_uninit:
+       zr364xx_board_uninit(cam);
+unregister:
        v4l2_device_unregister(&cam->v4l2_dev);
+free_cam:
        kfree(cam);
        return err;
 }