196c27377SValentina Manea /* 296c27377SValentina Manea * Copyright (C) 2003-2008 Takahiro Hirofuchi 3*bb7871adSNobuo Iwata * Copyright (C) 2015 Nobuo Iwata 496c27377SValentina Manea * 596c27377SValentina Manea * This is free software; you can redistribute it and/or modify 696c27377SValentina Manea * it under the terms of the GNU General Public License as published by 796c27377SValentina Manea * the Free Software Foundation; either version 2 of the License, or 896c27377SValentina Manea * (at your option) any later version. 996c27377SValentina Manea * 1096c27377SValentina Manea * This is distributed in the hope that it will be useful, 1196c27377SValentina Manea * but WITHOUT ANY WARRANTY; without even the implied warranty of 1296c27377SValentina Manea * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1396c27377SValentina Manea * GNU General Public License for more details. 1496c27377SValentina Manea * 1596c27377SValentina Manea * You should have received a copy of the GNU General Public License 1696c27377SValentina Manea * along with this program; if not, write to the Free Software 1796c27377SValentina Manea * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 1896c27377SValentina Manea * USA. 1996c27377SValentina Manea */ 2096c27377SValentina Manea 2196c27377SValentina Manea #include <linux/kthread.h> 2296c27377SValentina Manea #include <linux/export.h> 23*bb7871adSNobuo Iwata #include <linux/slab.h> 24*bb7871adSNobuo Iwata #include <linux/workqueue.h> 2596c27377SValentina Manea 2696c27377SValentina Manea #include "usbip_common.h" 2796c27377SValentina Manea 28*bb7871adSNobuo Iwata struct usbip_event { 29*bb7871adSNobuo Iwata struct list_head node; 30*bb7871adSNobuo Iwata struct usbip_device *ud; 31*bb7871adSNobuo Iwata }; 3296c27377SValentina Manea 33*bb7871adSNobuo Iwata static DEFINE_SPINLOCK(event_lock); 34*bb7871adSNobuo Iwata static LIST_HEAD(event_list); 35*bb7871adSNobuo Iwata 36*bb7871adSNobuo Iwata static void set_event(struct usbip_device *ud, unsigned long event) 37*bb7871adSNobuo Iwata { 38*bb7871adSNobuo Iwata unsigned long flags; 39*bb7871adSNobuo Iwata 40*bb7871adSNobuo Iwata spin_lock_irqsave(&ud->lock, flags); 41*bb7871adSNobuo Iwata ud->event |= event; 42*bb7871adSNobuo Iwata spin_unlock_irqrestore(&ud->lock, flags); 43*bb7871adSNobuo Iwata } 44*bb7871adSNobuo Iwata 45*bb7871adSNobuo Iwata static void unset_event(struct usbip_device *ud, unsigned long event) 46*bb7871adSNobuo Iwata { 47*bb7871adSNobuo Iwata unsigned long flags; 48*bb7871adSNobuo Iwata 49*bb7871adSNobuo Iwata spin_lock_irqsave(&ud->lock, flags); 50*bb7871adSNobuo Iwata ud->event &= ~event; 51*bb7871adSNobuo Iwata spin_unlock_irqrestore(&ud->lock, flags); 52*bb7871adSNobuo Iwata } 53*bb7871adSNobuo Iwata 54*bb7871adSNobuo Iwata static struct usbip_device *get_event(void) 55*bb7871adSNobuo Iwata { 56*bb7871adSNobuo Iwata struct usbip_event *ue = NULL; 57*bb7871adSNobuo Iwata struct usbip_device *ud = NULL; 58*bb7871adSNobuo Iwata unsigned long flags; 59*bb7871adSNobuo Iwata 60*bb7871adSNobuo Iwata spin_lock_irqsave(&event_lock, flags); 61*bb7871adSNobuo Iwata if (!list_empty(&event_list)) { 62*bb7871adSNobuo Iwata ue = list_first_entry(&event_list, struct usbip_event, node); 63*bb7871adSNobuo Iwata list_del(&ue->node); 64*bb7871adSNobuo Iwata } 65*bb7871adSNobuo Iwata spin_unlock_irqrestore(&event_lock, flags); 66*bb7871adSNobuo Iwata 67*bb7871adSNobuo Iwata if (ue) { 68*bb7871adSNobuo Iwata ud = ue->ud; 69*bb7871adSNobuo Iwata kfree(ue); 70*bb7871adSNobuo Iwata } 71*bb7871adSNobuo Iwata return ud; 72*bb7871adSNobuo Iwata } 73*bb7871adSNobuo Iwata 74*bb7871adSNobuo Iwata static struct task_struct *worker_context; 75*bb7871adSNobuo Iwata 76*bb7871adSNobuo Iwata static void event_handler(struct work_struct *work) 77*bb7871adSNobuo Iwata { 78*bb7871adSNobuo Iwata struct usbip_device *ud; 79*bb7871adSNobuo Iwata 80*bb7871adSNobuo Iwata if (worker_context == NULL) { 81*bb7871adSNobuo Iwata worker_context = current; 82*bb7871adSNobuo Iwata } 83*bb7871adSNobuo Iwata 84*bb7871adSNobuo Iwata while ((ud = get_event()) != NULL) { 8596c27377SValentina Manea usbip_dbg_eh("pending event %lx\n", ud->event); 8696c27377SValentina Manea 8796c27377SValentina Manea /* 8896c27377SValentina Manea * NOTE: shutdown must come first. 8996c27377SValentina Manea * Shutdown the device. 9096c27377SValentina Manea */ 9196c27377SValentina Manea if (ud->event & USBIP_EH_SHUTDOWN) { 9296c27377SValentina Manea ud->eh_ops.shutdown(ud); 93*bb7871adSNobuo Iwata unset_event(ud, USBIP_EH_SHUTDOWN); 9496c27377SValentina Manea } 9596c27377SValentina Manea 9696c27377SValentina Manea /* Reset the device. */ 9796c27377SValentina Manea if (ud->event & USBIP_EH_RESET) { 9896c27377SValentina Manea ud->eh_ops.reset(ud); 99*bb7871adSNobuo Iwata unset_event(ud, USBIP_EH_RESET); 10096c27377SValentina Manea } 10196c27377SValentina Manea 10296c27377SValentina Manea /* Mark the device as unusable. */ 10396c27377SValentina Manea if (ud->event & USBIP_EH_UNUSABLE) { 10496c27377SValentina Manea ud->eh_ops.unusable(ud); 105*bb7871adSNobuo Iwata unset_event(ud, USBIP_EH_UNUSABLE); 10696c27377SValentina Manea } 10796c27377SValentina Manea 10896c27377SValentina Manea /* Stop the error handler. */ 10996c27377SValentina Manea if (ud->event & USBIP_EH_BYE) 110*bb7871adSNobuo Iwata usbip_dbg_eh("removed %p\n", ud); 111*bb7871adSNobuo Iwata 112*bb7871adSNobuo Iwata wake_up(&ud->eh_waitq); 11396c27377SValentina Manea } 11496c27377SValentina Manea } 11596c27377SValentina Manea 11696c27377SValentina Manea int usbip_start_eh(struct usbip_device *ud) 11796c27377SValentina Manea { 11896c27377SValentina Manea init_waitqueue_head(&ud->eh_waitq); 11996c27377SValentina Manea ud->event = 0; 12096c27377SValentina Manea return 0; 12196c27377SValentina Manea } 12296c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_start_eh); 12396c27377SValentina Manea 12496c27377SValentina Manea void usbip_stop_eh(struct usbip_device *ud) 12596c27377SValentina Manea { 126*bb7871adSNobuo Iwata unsigned long pending = ud->event & ~USBIP_EH_BYE; 12796c27377SValentina Manea 128*bb7871adSNobuo Iwata if (!(ud->event & USBIP_EH_BYE)) 129*bb7871adSNobuo Iwata usbip_dbg_eh("usbip_eh stopping but not removed\n"); 130*bb7871adSNobuo Iwata 131*bb7871adSNobuo Iwata if (pending) 132*bb7871adSNobuo Iwata usbip_dbg_eh("usbip_eh waiting completion %lx\n", pending); 133*bb7871adSNobuo Iwata 134*bb7871adSNobuo Iwata wait_event_interruptible(ud->eh_waitq, !(ud->event & ~USBIP_EH_BYE)); 135*bb7871adSNobuo Iwata usbip_dbg_eh("usbip_eh has stopped\n"); 13696c27377SValentina Manea } 13796c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_stop_eh); 13896c27377SValentina Manea 139*bb7871adSNobuo Iwata #define WORK_QUEUE_NAME "usbip_event" 140*bb7871adSNobuo Iwata 141*bb7871adSNobuo Iwata static struct workqueue_struct *usbip_queue; 142*bb7871adSNobuo Iwata static DECLARE_WORK(usbip_work, event_handler); 143*bb7871adSNobuo Iwata 144*bb7871adSNobuo Iwata int usbip_init_eh(void) 145*bb7871adSNobuo Iwata { 146*bb7871adSNobuo Iwata usbip_queue = create_singlethread_workqueue(WORK_QUEUE_NAME); 147*bb7871adSNobuo Iwata if (usbip_queue == NULL) { 148*bb7871adSNobuo Iwata pr_err("failed to create usbip_event\n"); 149*bb7871adSNobuo Iwata return -ENOMEM; 150*bb7871adSNobuo Iwata } 151*bb7871adSNobuo Iwata return 0; 152*bb7871adSNobuo Iwata } 153*bb7871adSNobuo Iwata 154*bb7871adSNobuo Iwata void usbip_finish_eh(void) 155*bb7871adSNobuo Iwata { 156*bb7871adSNobuo Iwata flush_workqueue(usbip_queue); 157*bb7871adSNobuo Iwata destroy_workqueue(usbip_queue); 158*bb7871adSNobuo Iwata usbip_queue = NULL; 159*bb7871adSNobuo Iwata } 160*bb7871adSNobuo Iwata 16196c27377SValentina Manea void usbip_event_add(struct usbip_device *ud, unsigned long event) 16296c27377SValentina Manea { 163*bb7871adSNobuo Iwata struct usbip_event *ue; 16496c27377SValentina Manea unsigned long flags; 16596c27377SValentina Manea 166*bb7871adSNobuo Iwata if (ud->event & USBIP_EH_BYE) 167*bb7871adSNobuo Iwata return; 168*bb7871adSNobuo Iwata 169*bb7871adSNobuo Iwata set_event(ud, event); 170*bb7871adSNobuo Iwata 171*bb7871adSNobuo Iwata spin_lock_irqsave(&event_lock, flags); 172*bb7871adSNobuo Iwata 173*bb7871adSNobuo Iwata list_for_each_entry_reverse(ue, &event_list, node) { 174*bb7871adSNobuo Iwata if (ue->ud == ud) 175*bb7871adSNobuo Iwata goto out; 176*bb7871adSNobuo Iwata } 177*bb7871adSNobuo Iwata 178*bb7871adSNobuo Iwata ue = kmalloc(sizeof(struct usbip_event), GFP_ATOMIC); 179*bb7871adSNobuo Iwata if (ue == NULL) 180*bb7871adSNobuo Iwata goto out; 181*bb7871adSNobuo Iwata 182*bb7871adSNobuo Iwata ue->ud = ud; 183*bb7871adSNobuo Iwata 184*bb7871adSNobuo Iwata list_add_tail(&ue->node, &event_list); 185*bb7871adSNobuo Iwata queue_work(usbip_queue, &usbip_work); 186*bb7871adSNobuo Iwata 187*bb7871adSNobuo Iwata out: 188*bb7871adSNobuo Iwata spin_unlock_irqrestore(&event_lock, flags); 18996c27377SValentina Manea } 19096c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_event_add); 19196c27377SValentina Manea 19296c27377SValentina Manea int usbip_event_happened(struct usbip_device *ud) 19396c27377SValentina Manea { 19496c27377SValentina Manea int happened = 0; 19521619792SAndrew Goodbody unsigned long flags; 19696c27377SValentina Manea 19721619792SAndrew Goodbody spin_lock_irqsave(&ud->lock, flags); 19896c27377SValentina Manea if (ud->event != 0) 19996c27377SValentina Manea happened = 1; 20021619792SAndrew Goodbody spin_unlock_irqrestore(&ud->lock, flags); 20196c27377SValentina Manea 20296c27377SValentina Manea return happened; 20396c27377SValentina Manea } 20496c27377SValentina Manea EXPORT_SYMBOL_GPL(usbip_event_happened); 205*bb7871adSNobuo Iwata 206*bb7871adSNobuo Iwata int usbip_in_eh(struct task_struct *task) 207*bb7871adSNobuo Iwata { 208*bb7871adSNobuo Iwata if (task == worker_context) 209*bb7871adSNobuo Iwata return 1; 210*bb7871adSNobuo Iwata 211*bb7871adSNobuo Iwata return 0; 212*bb7871adSNobuo Iwata } 213*bb7871adSNobuo Iwata EXPORT_SYMBOL_GPL(usbip_in_eh); 214