1*96c27377SValentina Manea /* 2*96c27377SValentina Manea * Copyright (C) 2003-2008 Takahiro Hirofuchi 3*96c27377SValentina Manea * 4*96c27377SValentina Manea * This is free software; you can redistribute it and/or modify 5*96c27377SValentina Manea * it under the terms of the GNU General Public License as published by 6*96c27377SValentina Manea * the Free Software Foundation; either version 2 of the License, or 7*96c27377SValentina Manea * (at your option) any later version. 8*96c27377SValentina Manea * 9*96c27377SValentina Manea * This is distributed in the hope that it will be useful, 10*96c27377SValentina Manea * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*96c27377SValentina Manea * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*96c27377SValentina Manea * GNU General Public License for more details. 13*96c27377SValentina Manea * 14*96c27377SValentina Manea * You should have received a copy of the GNU General Public License 15*96c27377SValentina Manea * along with this program; if not, write to the Free Software 16*96c27377SValentina Manea * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 17*96c27377SValentina Manea * USA. 18*96c27377SValentina Manea */ 19*96c27377SValentina Manea 20*96c27377SValentina Manea #include <linux/kthread.h> 21*96c27377SValentina Manea #include <linux/export.h> 22*96c27377SValentina Manea 23*96c27377SValentina Manea #include "usbip_common.h" 24*96c27377SValentina Manea 25*96c27377SValentina Manea static int event_handler(struct usbip_device *ud) 26*96c27377SValentina Manea { 27*96c27377SValentina Manea usbip_dbg_eh("enter\n"); 28*96c27377SValentina Manea 29*96c27377SValentina Manea /* 30*96c27377SValentina Manea * Events are handled by only this thread. 31*96c27377SValentina Manea */ 32*96c27377SValentina Manea while (usbip_event_happened(ud)) { 33*96c27377SValentina Manea usbip_dbg_eh("pending event %lx\n", ud->event); 34*96c27377SValentina Manea 35*96c27377SValentina Manea /* 36*96c27377SValentina Manea * NOTE: shutdown must come first. 37*96c27377SValentina Manea * Shutdown the device. 38*96c27377SValentina Manea */ 39*96c27377SValentina Manea if (ud->event & USBIP_EH_SHUTDOWN) { 40*96c27377SValentina Manea ud->eh_ops.shutdown(ud); 41*96c27377SValentina Manea ud->event &= ~USBIP_EH_SHUTDOWN; 42*96c27377SValentina Manea } 43*96c27377SValentina Manea 44*96c27377SValentina Manea /* Reset the device. */ 45*96c27377SValentina Manea if (ud->event & USBIP_EH_RESET) { 46*96c27377SValentina Manea ud->eh_ops.reset(ud); 47*96c27377SValentina Manea ud->event &= ~USBIP_EH_RESET; 48*96c27377SValentina Manea } 49*96c27377SValentina Manea 50*96c27377SValentina Manea /* Mark the device as unusable. */ 51*96c27377SValentina Manea if (ud->event & USBIP_EH_UNUSABLE) { 52*96c27377SValentina Manea ud->eh_ops.unusable(ud); 53*96c27377SValentina Manea ud->event &= ~USBIP_EH_UNUSABLE; 54*96c27377SValentina Manea } 55*96c27377SValentina Manea 56*96c27377SValentina Manea /* Stop the error handler. */ 57*96c27377SValentina Manea if (ud->event & USBIP_EH_BYE) 58*96c27377SValentina Manea return -1; 59*96c27377SValentina Manea } 60*96c27377SValentina Manea 61*96c27377SValentina Manea return 0; 62*96c27377SValentina Manea } 63*96c27377SValentina Manea 64*96c27377SValentina Manea static int event_handler_loop(void *data) 65*96c27377SValentina Manea { 66*96c27377SValentina Manea struct usbip_device *ud = data; 67*96c27377SValentina Manea 68*96c27377SValentina Manea while (!kthread_should_stop()) { 69*96c27377SValentina Manea wait_event_interruptible(ud->eh_waitq, 70*96c27377SValentina Manea usbip_event_happened(ud) || 71*96c27377SValentina Manea kthread_should_stop()); 72*96c27377SValentina Manea usbip_dbg_eh("wakeup\n"); 73*96c27377SValentina Manea 74*96c27377SValentina Manea if (event_handler(ud) < 0) 75*96c27377SValentina Manea break; 76*96c27377SValentina Manea } 77*96c27377SValentina Manea 78*96c27377SValentina Manea return 0; 79*96c27377SValentina Manea } 80*96c27377SValentina Manea 81*96c27377SValentina Manea int usbip_start_eh(struct usbip_device *ud) 82*96c27377SValentina Manea { 83*96c27377SValentina Manea init_waitqueue_head(&ud->eh_waitq); 84*96c27377SValentina Manea ud->event = 0; 85*96c27377SValentina Manea 86*96c27377SValentina Manea ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh"); 87*96c27377SValentina Manea if (IS_ERR(ud->eh)) { 88*96c27377SValentina Manea pr_warn("Unable to start control thread\n"); 89*96c27377SValentina Manea return PTR_ERR(ud->eh); 90*96c27377SValentina Manea } 91*96c27377SValentina Manea 92*96c27377SValentina Manea return 0; 93*96c27377SValentina Manea } 94*96c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_start_eh); 95*96c27377SValentina Manea 96*96c27377SValentina Manea void usbip_stop_eh(struct usbip_device *ud) 97*96c27377SValentina Manea { 98*96c27377SValentina Manea if (ud->eh == current) 99*96c27377SValentina Manea return; /* do not wait for myself */ 100*96c27377SValentina Manea 101*96c27377SValentina Manea kthread_stop(ud->eh); 102*96c27377SValentina Manea usbip_dbg_eh("usbip_eh has finished\n"); 103*96c27377SValentina Manea } 104*96c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_stop_eh); 105*96c27377SValentina Manea 106*96c27377SValentina Manea void usbip_event_add(struct usbip_device *ud, unsigned long event) 107*96c27377SValentina Manea { 108*96c27377SValentina Manea unsigned long flags; 109*96c27377SValentina Manea 110*96c27377SValentina Manea spin_lock_irqsave(&ud->lock, flags); 111*96c27377SValentina Manea ud->event |= event; 112*96c27377SValentina Manea wake_up(&ud->eh_waitq); 113*96c27377SValentina Manea spin_unlock_irqrestore(&ud->lock, flags); 114*96c27377SValentina Manea } 115*96c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_event_add); 116*96c27377SValentina Manea 117*96c27377SValentina Manea int usbip_event_happened(struct usbip_device *ud) 118*96c27377SValentina Manea { 119*96c27377SValentina Manea int happened = 0; 120*96c27377SValentina Manea 121*96c27377SValentina Manea spin_lock(&ud->lock); 122*96c27377SValentina Manea if (ud->event != 0) 123*96c27377SValentina Manea happened = 1; 124*96c27377SValentina Manea spin_unlock(&ud->lock); 125*96c27377SValentina Manea 126*96c27377SValentina Manea return happened; 127*96c27377SValentina Manea } 128*96c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_event_happened); 129