2023-04-27 13:35:19

by Oliver Neukum

[permalink] [raw]
Subject: [PATCH 1/8] pwcd_usb: fix error handling in probe

If you support only one device, you need to roll back
back your counter in all cases if probe() fails.
That cannot be left to usb_pcwd_delete() because
that must be called conditionally.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Oliver Neukum <[email protected]>
---
drivers/watchdog/pcwd_usb.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index 8202f0a6b093..3a22291d633b 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -606,7 +606,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
struct usb_endpoint_descriptor *endpoint;
struct usb_pcwd_private *usb_pcwd = NULL;
int pipe;
- int retval = -ENOMEM;
+ int retval = -ENODEV;
int got_fw_rev;
unsigned char fw_rev_major, fw_rev_minor;
char fw_ver_str[20];
@@ -615,7 +615,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
cards_found++;
if (cards_found > 1) {
pr_err("This driver only supports 1 device\n");
- return -ENODEV;
+ goto error_count;
}

/* get the active interface descriptor */
@@ -624,11 +624,12 @@ static int usb_pcwd_probe(struct usb_interface *interface,
/* check out that we have a HID device */
if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
pr_err("The device isn't a Human Interface Device\n");
- return -ENODEV;
+ goto error_count;
}

if (iface_desc->desc.bNumEndpoints < 1)
- return -ENODEV;
+ goto error_count;
+

/* check out the endpoint: it has to be Interrupt & IN */
endpoint = &iface_desc->endpoint[0].desc;
@@ -636,16 +637,17 @@ static int usb_pcwd_probe(struct usb_interface *interface,
if (!usb_endpoint_is_int_in(endpoint)) {
/* we didn't find a Interrupt endpoint with direction IN */
pr_err("Couldn't find an INTR & IN endpoint\n");
- return -ENODEV;
+ goto error_count;
}

/* get a handle to the interrupt data pipe */
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);

/* allocate memory for our device and initialize it */
+ retval = -ENOMEM;
usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
if (usb_pcwd == NULL)
- goto error;
+ goto error_count;

usb_pcwd_device = usb_pcwd;

@@ -661,13 +663,13 @@ static int usb_pcwd_probe(struct usb_interface *interface,
GFP_KERNEL, &usb_pcwd->intr_dma);
if (!usb_pcwd->intr_buffer) {
pr_err("Out of memory\n");
- goto error;
+ goto error_delete;
}

/* allocate the urb's */
usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!usb_pcwd->intr_urb)
- goto error;
+ goto error_delete;

/* initialise the intr urb's */
usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
@@ -680,7 +682,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
pr_err("Problem registering interrupt URB\n");
retval = -EIO; /* failure */
- goto error;
+ goto error_delete;
}

/* The device exists and can be communicated with */
@@ -723,7 +725,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
retval = register_reboot_notifier(&usb_pcwd_notifier);
if (retval != 0) {
pr_err("cannot register reboot notifier (err=%d)\n", retval);
- goto error;
+ goto error_delete;
}

retval = misc_register(&usb_pcwd_temperature_miscdev);
@@ -752,10 +754,12 @@ static int usb_pcwd_probe(struct usb_interface *interface,
misc_deregister(&usb_pcwd_temperature_miscdev);
err_out_unregister_reboot:
unregister_reboot_notifier(&usb_pcwd_notifier);
-error:
+error_delete:
if (usb_pcwd)
usb_pcwd_delete(usb_pcwd);
usb_pcwd_device = NULL;
+error_count:
+ cards_found--;
return retval;
}

--
2.40.0