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