icE1usb: avoid system hang if USB transfer submission fails

If one of the isochronous or the interrupt EP URB cannot be submitted,
we should clean-up properly and avoid hanging the dahdi_cfg process
at 100% CPU itilization in an un-killable state.

Closes: OS#5477 (https://osmocom.org/issues/5477)
Change-Id: Ie6f7f11a64fae0d8c2b7c8ae90df886f2eb8f0c2
This commit is contained in:
Harald Welte 2022-03-12 12:29:18 +01:00
parent 13c4ed7c41
commit 0b4d75a504
1 changed files with 15 additions and 12 deletions

View File

@ -35,7 +35,7 @@
#include "ice1usb_proto.h" #include "ice1usb_proto.h"
#define VERSION "0.1" #define VERSION "0.2"
/* number of isochronous frames per URB */ /* number of isochronous frames per URB */
#define ICE1USB_MAX_ISOC_FRAMES 4 #define ICE1USB_MAX_ISOC_FRAMES 4
@ -756,19 +756,19 @@ static int e1u_d_startup(struct file *file, struct dahdi_span *span)
iso_in_complete, GFP_KERNEL); iso_in_complete, GFP_KERNEL);
if (rc) { if (rc) {
ieu_err(ieu, "error submitting IN ep URB %u (%d)", i, rc); ieu_err(ieu, "error submitting IN ep URB %u (%d)", i, rc);
goto err_isoc; goto err_isoc_in;
} }
rc = ice1usb_submit_isoc_urb(ieu, ieu->ep.iso_fb, &ieu->anchor.iso_fb, rc = ice1usb_submit_isoc_urb(ieu, ieu->ep.iso_fb, &ieu->anchor.iso_fb,
iso_fb_complete, GFP_KERNEL); iso_fb_complete, GFP_KERNEL);
if (rc) { if (rc) {
ieu_err(ieu, "error submitting FB ep URB %u (%d)", i, rc); ieu_err(ieu, "error submitting FB ep URB %u (%d)", i, rc);
goto err_isoc; goto err_isoc_fb;
} }
rc = ice1usb_submit_isoc_urb(ieu, ieu->ep.iso_out, &ieu->anchor.iso_out, rc = ice1usb_submit_isoc_urb(ieu, ieu->ep.iso_out, &ieu->anchor.iso_out,
iso_out_complete, GFP_KERNEL); iso_out_complete, GFP_KERNEL);
if (rc) { if (rc) {
ieu_err(ieu, "error submitting OUT ep URB %u (%d)", i, rc); ieu_err(ieu, "error submitting OUT ep URB %u (%d)", i, rc);
goto err_isoc; goto err_isoc_out;
} }
} }
} }
@ -792,10 +792,12 @@ static int e1u_d_startup(struct file *file, struct dahdi_span *span)
err_irq: err_irq:
usb_kill_anchored_urbs(&ieu->anchor.irq); usb_kill_anchored_urbs(&ieu->anchor.irq);
clear_bit(ICE1USB_IRQ_RUNNING, &ieu->flags); clear_bit(ICE1USB_IRQ_RUNNING, &ieu->flags);
err_isoc:
usb_kill_anchored_urbs(&ieu->anchor.iso_in);
usb_kill_anchored_urbs(&ieu->anchor.iso_out); usb_kill_anchored_urbs(&ieu->anchor.iso_out);
err_isoc_out:
usb_kill_anchored_urbs(&ieu->anchor.iso_fb); usb_kill_anchored_urbs(&ieu->anchor.iso_fb);
err_isoc_fb:
usb_kill_anchored_urbs(&ieu->anchor.iso_in);
err_isoc_in:
clear_bit(ICE1USB_ISOC_RUNNING, &ieu->flags); clear_bit(ICE1USB_ISOC_RUNNING, &ieu->flags);
ice1usb_set_altif(ieu, false); ice1usb_set_altif(ieu, false);
err: err:
@ -813,13 +815,14 @@ static int e1u_d_shutdown(struct dahdi_span *span)
ieu_dbg(ieu, "entering %s", __FUNCTION__); ieu_dbg(ieu, "entering %s", __FUNCTION__);
clear_bit(ICE1USB_ISOC_RUNNING, &ieu->flags); if (test_and_clear_bit(ICE1USB_ISOC_RUNNING, &ieu->flags)) {
clear_bit(ICE1USB_IRQ_RUNNING, &ieu->flags); usb_kill_anchored_urbs(&ieu->anchor.iso_in);
usb_kill_anchored_urbs(&ieu->anchor.iso_out);
usb_kill_anchored_urbs(&ieu->anchor.iso_fb);
}
usb_kill_anchored_urbs(&ieu->anchor.iso_in); if (test_and_clear_bit(ICE1USB_IRQ_RUNNING, &ieu->flags))
usb_kill_anchored_urbs(&ieu->anchor.iso_out); usb_kill_anchored_urbs(&ieu->anchor.irq);
usb_kill_anchored_urbs(&ieu->anchor.iso_fb);
usb_kill_anchored_urbs(&ieu->anchor.irq);
/* guard against devices unplugged (see ice1usb_disconnect) */ /* guard against devices unplugged (see ice1usb_disconnect) */
if (ieu->present) { if (ieu->present) {