| From d0e07a68a12f97af48b69cec1a9aa8359a189578 Mon Sep 17 00:00:00 2001 |
| From: Max Vozeler <mvz@vozeler.com> |
| Date: Tue, 21 Sep 2010 17:43:30 +0200 |
| Subject: [PATCH] staging: usbip: Process event flags without delay |
| |
| commit 584c5b7cf06194464240280483ee0376cdddbbae upstream. |
| |
| The way the event handler works can cause it to delay |
| events until eventual wakeup for another event. |
| |
| For example, on device detach (vhci): |
| |
| - Write to sysfs detach file |
| -> usbip_event_add(VDEV_EVENT_DOWN) |
| -> wakeup() |
| |
| #define VDEV_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET). |
| |
| - Event thread wakes up and passes the event to |
| event_handler() to process. |
| |
| - It processes and clears the USBIP_EH_SHUTDOWN |
| flag then returns. |
| |
| - The outer event loop (event_handler_loop()) calls |
| wait_event_interruptible(). |
| |
| The processing of the second flag which is part of |
| VDEV_EVENT_DOWN (USBIP_EH_RESET) did not happen yet. |
| It is delayed until the next event. |
| |
| This means the ->reset callback may not happen for |
| a long time (if ever), leaving the usbip port in a |
| weird state which prevents its reuse. |
| |
| This patch changes the handler to process all flags |
| before waiting for another wakeup. |
| |
| I have verified this change to fix a problem which |
| prevented reattach of a usbip device. It also helps |
| for socket errors which missed the RESET as well. |
| |
| The delayed event processing also affects the stub |
| side of usbip and the error handling there. |
| |
| Signed-off-by: Max Vozeler <mvz@vozeler.com> |
| Reported-by: Marco Lancione <marco@optikam.com> |
| Tested-by: Luc Jalbert <ljalbert@optikam.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| --- |
| drivers/staging/usbip/usbip_event.c | 16 +++------------- |
| 1 files changed, 3 insertions(+), 13 deletions(-) |
| |
| diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c |
| index a2566f1..af3832b 100644 |
| --- a/drivers/staging/usbip/usbip_event.c |
| +++ b/drivers/staging/usbip/usbip_event.c |
| @@ -38,21 +38,13 @@ static int event_handler(struct usbip_device *ud) |
| ud->eh_ops.shutdown(ud); |
| |
| ud->event &= ~USBIP_EH_SHUTDOWN; |
| - |
| - break; |
| } |
| |
| - /* Stop the error handler. */ |
| - if (ud->event & USBIP_EH_BYE) |
| - return -1; |
| - |
| /* Reset the device. */ |
| if (ud->event & USBIP_EH_RESET) { |
| ud->eh_ops.reset(ud); |
| |
| ud->event &= ~USBIP_EH_RESET; |
| - |
| - break; |
| } |
| |
| /* Mark the device as unusable. */ |
| @@ -60,13 +52,11 @@ static int event_handler(struct usbip_device *ud) |
| ud->eh_ops.unusable(ud); |
| |
| ud->event &= ~USBIP_EH_UNUSABLE; |
| - |
| - break; |
| } |
| |
| - /* NOTREACHED */ |
| - printk(KERN_ERR "%s: unknown event\n", __func__); |
| - return -1; |
| + /* Stop the error handler. */ |
| + if (ud->event & USBIP_EH_BYE) |
| + return -1; |
| } |
| |
| return 0; |
| -- |
| 1.7.0.4 |
| |