USB: Phidgets should check create_device_file() return value

device_create_file() could fail, add proper error paths for this condition.

Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index d9ac7f9..6b59b62 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -215,9 +215,12 @@
 	struct motorcontrol *mc = dev_get_drvdata(dev);			\
 									\
 	return sprintf(buf, "%d\n", mc->speed[value]);			\
-}									\
-static DEVICE_ATTR(speed##value, S_IWUGO | S_IRUGO,			\
-		show_speed##value, set_speed##value);
+}
+
+#define speed_attr(value) 						\
+	__ATTR(speed##value, S_IWUGO | S_IRUGO, 			\
+		show_speed##value, set_speed##value)
+
 show_set_speed(0);
 show_set_speed(1);
 
@@ -250,9 +253,12 @@
 	struct motorcontrol *mc = dev_get_drvdata(dev);			\
 									\
 	return sprintf(buf, "%d\n", mc->acceleration[value]);		\
-}									\
-static DEVICE_ATTR(acceleration##value, S_IWUGO | S_IRUGO,		\
-		show_acceleration##value, set_acceleration##value);
+}
+
+#define acceleration_attr(value)	\
+	__ATTR(acceleration##value, S_IWUGO | S_IRUGO,			\
+		show_acceleration##value, set_acceleration##value)
+
 show_set_acceleration(0);
 show_set_acceleration(1);
 
@@ -264,8 +270,10 @@
 	struct motorcontrol *mc = dev_get_drvdata(dev);			\
 									\
 	return sprintf(buf, "%dmA\n", (int)mc->_current[value]);	\
-}									\
-static DEVICE_ATTR(current##value, S_IRUGO, show_current##value, NULL);
+}
+
+#define current_attr(value)	\
+	__ATTR(current##value, S_IRUGO, show_current##value, NULL)
 
 show_current(0);
 show_current(1);
@@ -278,14 +286,29 @@
 	struct motorcontrol *mc = dev_get_drvdata(dev);			\
 									\
 	return sprintf(buf, "%d\n", (int)mc->inputs[value]);		\
-}									\
-static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
+}
+
+#define input_attr(value)	\
+	__ATTR(input##value, S_IRUGO, show_input##value, NULL)
 
 show_input(0);
 show_input(1);
 show_input(2);
 show_input(3);
 
+static struct device_attribute dev_attrs[] = {
+	input_attr(0),
+	input_attr(1),
+	input_attr(2),
+	input_attr(3),
+	speed_attr(0),
+	speed_attr(1),
+	acceleration_attr(0),
+	acceleration_attr(1),
+	current_attr(0),
+	current_attr(1)
+};
+
 static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -293,7 +316,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct motorcontrol *mc;
 	int pipe, maxp, rc = -ENOMEM;
-	int bit, value;
+	int bit, value, i;
 
 	interface = intf->cur_altsetting;
 	if (interface->desc.bNumEndpoints != 1)
@@ -355,24 +378,18 @@
 		goto out;
 	}
 
-	device_create_file(mc->dev, &dev_attr_input0);
-	device_create_file(mc->dev, &dev_attr_input1);
-	device_create_file(mc->dev, &dev_attr_input2);
-	device_create_file(mc->dev, &dev_attr_input3);
-
-	device_create_file(mc->dev, &dev_attr_speed0);
-	device_create_file(mc->dev, &dev_attr_speed1);
-
-	device_create_file(mc->dev, &dev_attr_acceleration0);
-	device_create_file(mc->dev, &dev_attr_acceleration1);
-
-	device_create_file(mc->dev, &dev_attr_current0);
-	device_create_file(mc->dev, &dev_attr_current1);
+	for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
+		rc = device_create_file(mc->dev, &dev_attrs[i]);
+		if (rc)
+			goto out2;
+	}
 
 	dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
 
 	return 0;
-
+out2:
+	while (i-- > 0)
+		device_remove_file(mc->dev, &dev_attrs[i]);
 out:
 	if (mc) {
 		if (mc->irq)
@@ -393,6 +410,7 @@
 static void motorcontrol_disconnect(struct usb_interface *interface)
 {
 	struct motorcontrol *mc;
+	int i;
 
 	mc = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
@@ -405,19 +423,8 @@
 
 	cancel_delayed_work(&mc->do_notify);
 
-	device_remove_file(mc->dev, &dev_attr_input0);
-	device_remove_file(mc->dev, &dev_attr_input1);
-	device_remove_file(mc->dev, &dev_attr_input2);
-	device_remove_file(mc->dev, &dev_attr_input3);
-
-	device_remove_file(mc->dev, &dev_attr_speed0);
-	device_remove_file(mc->dev, &dev_attr_speed1);
-
-	device_remove_file(mc->dev, &dev_attr_acceleration0);
-	device_remove_file(mc->dev, &dev_attr_acceleration1);
-
-	device_remove_file(mc->dev, &dev_attr_current0);
-	device_remove_file(mc->dev, &dev_attr_current1);
+	for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
+		device_remove_file(mc->dev, &dev_attrs[i]);
 
 	device_unregister(mc->dev);