diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-17 09:50:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-17 09:50:12 -0700 |
commit | 26e9a397774a0e94efbb8a0bf4a952c28d808cab (patch) | |
tree | fee2211b32a30c71bd22543acb791feeebd91b35 /drivers/staging/usbip/usbip_event.c | |
parent | bdbf0ac7e187b2b757216e653e64f8b808b9077e (diff) | |
parent | 99e06e372378c5833a0c60274b645dfb2e4a4b08 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (25 commits)
staging: at76_usb wireless driver
Staging: workaround build system bug
Staging: Lindent sxg.c
Staging: SLICOSS: Call pci_release_regions at driver exit
Staging: SLICOSS: Fix remaining type names
Staging: SLICOSS: Fix warnings due to static usage
Staging: SLICOSS: lots of checkpatch fixes
Staging: go7007 v4l fixes
Staging: Fix gcc warnings in sxg
Staging: add echo cancelation module
Staging: add wlan-ng prism2 usb driver
Staging: add w35und wifi driver
Staging: USB/IP: add host driver
Staging: USB/IP: add client driver
Staging: USB/IP: add common functions needed
Staging: add the go7007 video driver
Staging: add me4000 pci data collection driver
Staging: add me4000 firmware files
Staging: add sxg network driver
Staging: add Alacritech slicoss network driver
...
Fixed up conflicts due to taint flags changes and MAINTAINERS cleanup in
MAINTAINERS, include/linux/kernel.h and kernel/panic.c.
Diffstat (limited to 'drivers/staging/usbip/usbip_event.c')
-rw-r--r-- | drivers/staging/usbip/usbip_event.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c new file mode 100644 index 00000000000..4318553ab20 --- /dev/null +++ b/drivers/staging/usbip/usbip_event.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2003-2008 Takahiro Hirofuchi + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "usbip_common.h" + +static int event_handler(struct usbip_device *ud) +{ + dbg_eh("enter\n"); + + /* + * Events are handled by only this thread. + */ + while (usbip_event_happend(ud)) { + dbg_eh("pending event %lx\n", ud->event); + + /* + * NOTE: shutdown must come first. + * Shutdown the device. + */ + if (ud->event & USBIP_EH_SHUTDOWN) { + 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. */ + if (ud->event & USBIP_EH_UNUSABLE) { + ud->eh_ops.unusable(ud); + + ud->event &= ~USBIP_EH_UNUSABLE; + + break; + } + + /* NOTREACHED */ + printk(KERN_ERR "%s: unknown event\n", __func__); + return -1; + } + + return 0; +} + +static void event_handler_loop(struct usbip_task *ut) +{ + struct usbip_device *ud = container_of(ut, struct usbip_device, eh); + + while (1) { + if (signal_pending(current)) { + dbg_eh("signal catched!\n"); + break; + } + + if (event_handler(ud) < 0) + break; + + wait_event_interruptible(ud->eh_waitq, usbip_event_happend(ud)); + dbg_eh("wakeup\n"); + } +} + +void usbip_start_eh(struct usbip_device *ud) +{ + struct usbip_task *eh = &ud->eh; + + init_waitqueue_head(&ud->eh_waitq); + ud->event = 0; + + usbip_task_init(eh, "usbip_eh", event_handler_loop); + + kernel_thread(usbip_thread, (void *)eh, 0); + + wait_for_completion(&eh->thread_done); +} +EXPORT_SYMBOL_GPL(usbip_start_eh); + +void usbip_stop_eh(struct usbip_device *ud) +{ + struct usbip_task *eh = &ud->eh; + + wait_for_completion(&eh->thread_done); + dbg_eh("usbip_eh has finished\n"); +} +EXPORT_SYMBOL_GPL(usbip_stop_eh); + +void usbip_event_add(struct usbip_device *ud, unsigned long event) +{ + spin_lock(&ud->lock); + + ud->event |= event; + + wake_up(&ud->eh_waitq); + + spin_unlock(&ud->lock); +} +EXPORT_SYMBOL_GPL(usbip_event_add); + +int usbip_event_happend(struct usbip_device *ud) +{ + int happend = 0; + + spin_lock(&ud->lock); + + if (ud->event != 0) + happend = 1; + + spin_unlock(&ud->lock); + + return happend; +} +EXPORT_SYMBOL_GPL(usbip_event_happend); |