V4L/DVB (4742): Drivers/media/video: handle sysfs errors

Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index c77b85c..46c1148 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -1024,12 +1024,25 @@
 static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
 			 NULL);
 
-static void pwc_create_sysfs_files(struct video_device *vdev)
+static int pwc_create_sysfs_files(struct video_device *vdev)
 {
 	struct pwc_device *pdev = video_get_drvdata(vdev);
-	if (pdev->features & FEATURE_MOTOR_PANTILT)
-		video_device_create_file(vdev, &class_device_attr_pan_tilt);
-	video_device_create_file(vdev, &class_device_attr_button);
+	int rc;
+
+	rc = video_device_create_file(vdev, &class_device_attr_button);
+	if (rc)
+		goto err;
+	if (pdev->features & FEATURE_MOTOR_PANTILT) {
+		rc = video_device_create_file(vdev,&class_device_attr_pan_tilt);
+		if (rc) goto err_button;
+	}
+
+	return 0;
+
+err_button:
+	video_device_remove_file(vdev, &class_device_attr_button);
+err:
+	return rc;
 }
 
 static void pwc_remove_sysfs_files(struct video_device *vdev)
@@ -1408,7 +1421,7 @@
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct pwc_device *pdev = NULL;
 	int vendor_id, product_id, type_id;
-	int i, hint;
+	int i, hint, rc;
 	int features = 0;
 	int video_nr = -1; /* default: use next available device */
 	char serial_number[30], *name;
@@ -1709,9 +1722,8 @@
 	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
 	if (i < 0) {
 		PWC_ERROR("Failed to register as video device (%d).\n", i);
-		video_device_release(pdev->vdev); /* Drip... drip... drip... */
-		kfree(pdev); /* Oops, no memory leaks please */
-		return -EIO;
+		rc = i;
+		goto err;
 	}
 	else {
 		PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
@@ -1723,13 +1735,24 @@
 
 	PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
 	usb_set_intfdata (intf, pdev);
-	pwc_create_sysfs_files(pdev->vdev);
+	rc = pwc_create_sysfs_files(pdev->vdev);
+	if (rc)
+		goto err_unreg;
 
 	/* Set the leds off */
 	pwc_set_leds(pdev, 0, 0);
 	pwc_camera_power(pdev, 0);
 
 	return 0;
+
+err_unreg:
+	if (hint < MAX_DEV_HINTS)
+		device_hint[hint].pdev = NULL;
+	video_unregister_device(pdev->vdev);
+err:
+	video_device_release(pdev->vdev); /* Drip... drip... drip... */
+	kfree(pdev); /* Oops, no memory leaks please */
+	return rc;
 }
 
 /* The user janked out the cable... */