1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "usbip_common.h"
21#include <linux/kthread.h>
22
23static int event_handler(struct usbip_device *ud)
24{
25 usbip_dbg_eh("enter\n");
26
27
28
29
30 while (usbip_event_happened(ud)) {
31 usbip_dbg_eh("pending event %lx\n", ud->event);
32
33
34
35
36
37 if (ud->event & USBIP_EH_SHUTDOWN) {
38 ud->eh_ops.shutdown(ud);
39
40 ud->event &= ~USBIP_EH_SHUTDOWN;
41
42 break;
43 }
44
45
46 if (ud->event & USBIP_EH_BYE)
47 return -1;
48
49
50 if (ud->event & USBIP_EH_RESET) {
51 ud->eh_ops.reset(ud);
52
53 ud->event &= ~USBIP_EH_RESET;
54
55 break;
56 }
57
58
59 if (ud->event & USBIP_EH_UNUSABLE) {
60 ud->eh_ops.unusable(ud);
61
62 ud->event &= ~USBIP_EH_UNUSABLE;
63
64 break;
65 }
66
67
68 printk(KERN_ERR "%s: unknown event\n", __func__);
69 return -1;
70 }
71
72 return 0;
73}
74
75static void event_handler_loop(struct usbip_task *ut)
76{
77 struct usbip_device *ud = container_of(ut, struct usbip_device, eh);
78
79 while (1) {
80 if (signal_pending(current)) {
81 usbip_dbg_eh("signal catched!\n");
82 break;
83 }
84
85 if (event_handler(ud) < 0)
86 break;
87
88 wait_event_interruptible(ud->eh_waitq,
89 usbip_event_happened(ud));
90 usbip_dbg_eh("wakeup\n");
91 }
92}
93
94int usbip_start_eh(struct usbip_device *ud)
95{
96 struct usbip_task *eh = &ud->eh;
97 struct task_struct *th;
98
99 init_waitqueue_head(&ud->eh_waitq);
100 ud->event = 0;
101
102 usbip_task_init(eh, "usbip_eh", event_handler_loop);
103
104 th = kthread_run(usbip_thread, (void *)eh, "usbip");
105 if (IS_ERR(th)) {
106 printk(KERN_WARNING
107 "Unable to start control thread\n");
108 return PTR_ERR(th);
109 }
110
111 wait_for_completion(&eh->thread_done);
112 return 0;
113}
114EXPORT_SYMBOL_GPL(usbip_start_eh);
115
116void usbip_stop_eh(struct usbip_device *ud)
117{
118 struct usbip_task *eh = &ud->eh;
119
120 wait_for_completion(&eh->thread_done);
121 usbip_dbg_eh("usbip_eh has finished\n");
122}
123EXPORT_SYMBOL_GPL(usbip_stop_eh);
124
125void usbip_event_add(struct usbip_device *ud, unsigned long event)
126{
127 spin_lock(&ud->lock);
128
129 ud->event |= event;
130
131 wake_up(&ud->eh_waitq);
132
133 spin_unlock(&ud->lock);
134}
135EXPORT_SYMBOL_GPL(usbip_event_add);
136
137int usbip_event_happened(struct usbip_device *ud)
138{
139 int happened = 0;
140
141 spin_lock(&ud->lock);
142
143 if (ud->event != 0)
144 happened = 1;
145
146 spin_unlock(&ud->lock);
147
148 return happened;
149}
150EXPORT_SYMBOL_GPL(usbip_event_happened);
151