diff options
author | Thomas Pugliese <thomas.pugliese@gmail.com> | 2013-08-09 10:25:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-12 18:41:08 -0400 |
commit | c654ecbbfefbeec8fbf202e117364bff48ecaea3 (patch) | |
tree | 262c335c73b088ef1851c926f7bfe5f95f8cf33c /drivers/uwb | |
parent | 6dd433e6cf2475ce8abec1b467720858c24450eb (diff) |
HWA RC: fix a kernel panic when unplugging the HWA dongle
This patch fixes a kernel panic that can occur when unplugging the HWA
dongle while a downstream device is in the process of disconnecting.
This involved 2 changes. First, call usb_lock_device_for_reset before
usb_reset_device to synchronize the HWA's post_rest and disconnect
routines. Second, set the hwarc->neep_urb and hwarc->rd_buffer to NULL
when they are freed in the error path in the post_reset routine. This
prevents a double free when the disconnect routine is called and attempts
to free those resources again.
Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/uwb')
-rw-r--r-- | drivers/uwb/hwa-rc.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 0621abef9b4a..0257f35cfb9d 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c | |||
@@ -611,7 +611,16 @@ static | |||
611 | int hwarc_reset(struct uwb_rc *uwb_rc) | 611 | int hwarc_reset(struct uwb_rc *uwb_rc) |
612 | { | 612 | { |
613 | struct hwarc *hwarc = uwb_rc->priv; | 613 | struct hwarc *hwarc = uwb_rc->priv; |
614 | return usb_reset_device(hwarc->usb_dev); | 614 | int result; |
615 | |||
616 | /* device lock must be held when calling usb_reset_device. */ | ||
617 | result = usb_lock_device_for_reset(hwarc->usb_dev, NULL); | ||
618 | if (result >= 0) { | ||
619 | result = usb_reset_device(hwarc->usb_dev); | ||
620 | usb_unlock_device(hwarc->usb_dev); | ||
621 | } | ||
622 | |||
623 | return result; | ||
615 | } | 624 | } |
616 | 625 | ||
617 | /** | 626 | /** |
@@ -709,8 +718,10 @@ static int hwarc_neep_init(struct uwb_rc *rc) | |||
709 | 718 | ||
710 | error_neep_submit: | 719 | error_neep_submit: |
711 | usb_free_urb(hwarc->neep_urb); | 720 | usb_free_urb(hwarc->neep_urb); |
721 | hwarc->neep_urb = NULL; | ||
712 | error_urb_alloc: | 722 | error_urb_alloc: |
713 | free_page((unsigned long)hwarc->rd_buffer); | 723 | free_page((unsigned long)hwarc->rd_buffer); |
724 | hwarc->rd_buffer = NULL; | ||
714 | error_rd_buffer: | 725 | error_rd_buffer: |
715 | return -ENOMEM; | 726 | return -ENOMEM; |
716 | } | 727 | } |
@@ -723,7 +734,10 @@ static void hwarc_neep_release(struct uwb_rc *rc) | |||
723 | 734 | ||
724 | usb_kill_urb(hwarc->neep_urb); | 735 | usb_kill_urb(hwarc->neep_urb); |
725 | usb_free_urb(hwarc->neep_urb); | 736 | usb_free_urb(hwarc->neep_urb); |
737 | hwarc->neep_urb = NULL; | ||
738 | |||
726 | free_page((unsigned long)hwarc->rd_buffer); | 739 | free_page((unsigned long)hwarc->rd_buffer); |
740 | hwarc->rd_buffer = NULL; | ||
727 | } | 741 | } |
728 | 742 | ||
729 | /** | 743 | /** |