Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / usb / mon / mon_main.c
1 /*
2  * The USB Monitor, inspired by Dave Harding's USBMon.
3  *
4  * mon_main.c: Main file, module initiation and exit, registrations, etc.
5  *
6  * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/usb.h>
12 #include <linux/debugfs.h>
13 #include <linux/smp_lock.h>
14 #include <linux/notifier.h>
15 #include <linux/mutex.h>
16
17 #include "usb_mon.h"
18 #include "../core/hcd.h"
19
20 static void mon_submit(struct usb_bus *ubus, struct urb *urb);
21 static void mon_complete(struct usb_bus *ubus, struct urb *urb);
22 static void mon_stop(struct mon_bus *mbus);
23 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
24 static void mon_bus_drop(struct kref *r);
25 static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus);
26
27 DEFINE_MUTEX(mon_lock);
28
29 static struct dentry *mon_dir;          /* /dbg/usbmon */
30 static LIST_HEAD(mon_buses);            /* All buses we know: struct mon_bus */
31
32 /*
33  * Link a reader into the bus.
34  *
35  * This must be called with mon_lock taken because of mbus->ref.
36  */
37 void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
38 {
39         unsigned long flags;
40         struct usb_bus *ubus;
41
42         spin_lock_irqsave(&mbus->lock, flags);
43         if (mbus->nreaders == 0) {
44                 ubus = mbus->u_bus;
45                 if (ubus->monitored) {
46                         /*
47                          * Something is really broken, refuse to go on and
48                          * possibly corrupt ops pointers or worse.
49                          */
50                         printk(KERN_ERR TAG ": bus %d is already monitored\n",
51                             ubus->busnum);
52                         spin_unlock_irqrestore(&mbus->lock, flags);
53                         return;
54                 }
55                 ubus->monitored = 1;
56         }
57         mbus->nreaders++;
58         list_add_tail(&r->r_link, &mbus->r_list);
59         spin_unlock_irqrestore(&mbus->lock, flags);
60
61         kref_get(&mbus->ref);
62 }
63
64 /*
65  * Unlink reader from the bus.
66  *
67  * This is called with mon_lock taken, so we can decrement mbus->ref.
68  */
69 void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
70 {
71         unsigned long flags;
72
73         spin_lock_irqsave(&mbus->lock, flags);
74         list_del(&r->r_link);
75         --mbus->nreaders;
76         if (mbus->nreaders == 0)
77                 mon_stop(mbus);
78         spin_unlock_irqrestore(&mbus->lock, flags);
79
80         kref_put(&mbus->ref, mon_bus_drop);
81 }
82
83 /*
84  */
85 static void mon_submit(struct usb_bus *ubus, struct urb *urb)
86 {
87         struct mon_bus *mbus;
88         unsigned long flags;
89         struct list_head *pos;
90         struct mon_reader *r;
91
92         mbus = ubus->mon_bus;
93         if (mbus == NULL)
94                 goto out_unlocked;
95
96         spin_lock_irqsave(&mbus->lock, flags);
97         if (mbus->nreaders == 0)
98                 goto out_locked;
99
100         mbus->cnt_events++;
101         list_for_each (pos, &mbus->r_list) {
102                 r = list_entry(pos, struct mon_reader, r_link);
103                 r->rnf_submit(r->r_data, urb);
104         }
105
106         spin_unlock_irqrestore(&mbus->lock, flags);
107         return;
108
109 out_locked:
110         spin_unlock_irqrestore(&mbus->lock, flags);
111 out_unlocked:
112         return;
113 }
114
115 /*
116  */
117 static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
118 {
119         struct mon_bus *mbus;
120         unsigned long flags;
121         struct list_head *pos;
122         struct mon_reader *r;
123
124         mbus = ubus->mon_bus;
125         if (mbus == NULL)
126                 goto out_unlocked;
127
128         spin_lock_irqsave(&mbus->lock, flags);
129         if (mbus->nreaders == 0)
130                 goto out_locked;
131
132         mbus->cnt_events++;
133         list_for_each (pos, &mbus->r_list) {
134                 r = list_entry(pos, struct mon_reader, r_link);
135                 r->rnf_error(r->r_data, urb, error);
136         }
137
138         spin_unlock_irqrestore(&mbus->lock, flags);
139         return;
140
141 out_locked:
142         spin_unlock_irqrestore(&mbus->lock, flags);
143 out_unlocked:
144         return;
145 }
146
147 /*
148  */
149 static void mon_complete(struct usb_bus *ubus, struct urb *urb)
150 {
151         struct mon_bus *mbus;
152         unsigned long flags;
153         struct list_head *pos;
154         struct mon_reader *r;
155
156         mbus = ubus->mon_bus;
157         if (mbus == NULL) {
158                 /*
159                  * This should not happen.
160                  * At this point we do not even know the bus number...
161                  */
162                 printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n",
163                     urb->pipe);
164                 return;
165         }
166
167         spin_lock_irqsave(&mbus->lock, flags);
168         mbus->cnt_events++;
169         list_for_each (pos, &mbus->r_list) {
170                 r = list_entry(pos, struct mon_reader, r_link);
171                 r->rnf_complete(r->r_data, urb);
172         }
173         spin_unlock_irqrestore(&mbus->lock, flags);
174 }
175
176 /* int (*unlink_urb) (struct urb *urb, int status); */
177
178 /*
179  * Stop monitoring.
180  */
181 static void mon_stop(struct mon_bus *mbus)
182 {
183         struct usb_bus *ubus = mbus->u_bus;
184
185         /*
186          * A stop can be called for a dissolved mon_bus in case of
187          * a reader staying across an rmmod foo_hcd.
188          */
189         if (ubus != NULL) {
190                 ubus->monitored = 0;
191                 mb();
192         }
193 }
194
195 /*
196  * Add a USB bus (usually by a modprobe foo-hcd)
197  *
198  * This does not return an error code because the core cannot care less
199  * if monitoring is not established.
200  */
201 static void mon_bus_add(struct usb_bus *ubus)
202 {
203         mon_bus_init(mon_dir, ubus);
204 }
205
206 /*
207  * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
208  */
209 static void mon_bus_remove(struct usb_bus *ubus)
210 {
211         struct mon_bus *mbus = ubus->mon_bus;
212
213         mutex_lock(&mon_lock);
214         list_del(&mbus->bus_link);
215         debugfs_remove(mbus->dent_t);
216         debugfs_remove(mbus->dent_s);
217
218         mon_dissolve(mbus, ubus);
219         kref_put(&mbus->ref, mon_bus_drop);
220         mutex_unlock(&mon_lock);
221 }
222
223 static int mon_notify(struct notifier_block *self, unsigned long action,
224                       void *dev)
225 {
226         switch (action) {
227         case USB_BUS_ADD:
228                 mon_bus_add(dev);
229                 break;
230         case USB_BUS_REMOVE:
231                 mon_bus_remove(dev);
232         }
233         return NOTIFY_OK;
234 }
235
236 static struct notifier_block mon_nb = {
237         .notifier_call =        mon_notify,
238 };
239
240 /*
241  * Ops
242  */
243 static struct usb_mon_operations mon_ops_0 = {
244         .urb_submit =   mon_submit,
245         .urb_submit_error = mon_submit_error,
246         .urb_complete = mon_complete,
247 };
248
249 /*
250  * Tear usb_bus and mon_bus apart.
251  */
252 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
253 {
254
255         /*
256          * Never happens, but...
257          */
258         if (ubus->monitored) {
259                 printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n",
260                     ubus->busnum);
261                 ubus->monitored = 0;
262                 mb();
263         }
264
265         ubus->mon_bus = NULL;
266         mbus->u_bus = NULL;
267         mb();
268         // usb_bus_put(ubus);
269 }
270
271 /*
272  */
273 static void mon_bus_drop(struct kref *r)
274 {
275         struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
276         kfree(mbus);
277 }
278
279 /*
280  * Initialize a bus for us:
281  *  - allocate mon_bus
282  *  - refcount USB bus struct
283  *  - link
284  */
285 static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
286 {
287         struct dentry *d;
288         struct mon_bus *mbus;
289         enum { NAMESZ = 10 };
290         char name[NAMESZ];
291         int rc;
292
293         if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
294                 goto err_alloc;
295         kref_init(&mbus->ref);
296         spin_lock_init(&mbus->lock);
297         INIT_LIST_HEAD(&mbus->r_list);
298
299         /*
300          * This usb_bus_get here is superfluous, because we receive
301          * a notification if usb_bus is about to be removed.
302          */
303         // usb_bus_get(ubus);
304         mbus->u_bus = ubus;
305         ubus->mon_bus = mbus;
306
307         rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
308         if (rc <= 0 || rc >= NAMESZ)
309                 goto err_print_t;
310         d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text);
311         if (d == NULL)
312                 goto err_create_t;
313         mbus->dent_t = d;
314
315         rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
316         if (rc <= 0 || rc >= NAMESZ)
317                 goto err_print_s;
318         d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat);
319         if (d == NULL)
320                 goto err_create_s;
321         mbus->dent_s = d;
322
323         mutex_lock(&mon_lock);
324         list_add_tail(&mbus->bus_link, &mon_buses);
325         mutex_unlock(&mon_lock);
326         return;
327
328 err_create_s:
329 err_print_s:
330         debugfs_remove(mbus->dent_t);
331 err_create_t:
332 err_print_t:
333         kfree(mbus);
334 err_alloc:
335         return;
336 }
337
338 static int __init mon_init(void)
339 {
340         struct usb_bus *ubus;
341         struct dentry *mondir;
342
343         mondir = debugfs_create_dir("usbmon", NULL);
344         if (IS_ERR(mondir)) {
345                 printk(KERN_NOTICE TAG ": debugfs is not available\n");
346                 return -ENODEV;
347         }
348         if (mondir == NULL) {
349                 printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
350                 return -ENODEV;
351         }
352         mon_dir = mondir;
353
354         if (usb_mon_register(&mon_ops_0) != 0) {
355                 printk(KERN_NOTICE TAG ": unable to register with the core\n");
356                 debugfs_remove(mondir);
357                 return -ENODEV;
358         }
359         // MOD_INC_USE_COUNT(which_module?);
360
361         usb_register_notify(&mon_nb);
362
363         mutex_lock(&usb_bus_list_lock);
364         list_for_each_entry (ubus, &usb_bus_list, bus_list) {
365                 mon_bus_init(mondir, ubus);
366         }
367         mutex_unlock(&usb_bus_list_lock);
368         return 0;
369 }
370
371 static void __exit mon_exit(void)
372 {
373         struct mon_bus *mbus;
374         struct list_head *p;
375
376         usb_unregister_notify(&mon_nb);
377         usb_mon_deregister();
378
379         mutex_lock(&mon_lock);
380         while (!list_empty(&mon_buses)) {
381                 p = mon_buses.next;
382                 mbus = list_entry(p, struct mon_bus, bus_link);
383                 list_del(p);
384
385                 debugfs_remove(mbus->dent_t);
386                 debugfs_remove(mbus->dent_s);
387
388                 /*
389                  * This never happens, because the open/close paths in
390                  * file level maintain module use counters and so rmmod fails
391                  * before reaching here. However, better be safe...
392                  */
393                 if (mbus->nreaders) {
394                         printk(KERN_ERR TAG
395                             ": Outstanding opens (%d) on usb%d, leaking...\n",
396                             mbus->nreaders, mbus->u_bus->busnum);
397                         atomic_set(&mbus->ref.refcount, 2);     /* Force leak */
398                 }
399
400                 mon_dissolve(mbus, mbus->u_bus);
401                 kref_put(&mbus->ref, mon_bus_drop);
402         }
403         mutex_unlock(&mon_lock);
404
405         debugfs_remove(mon_dir);
406 }
407
408 module_init(mon_init);
409 module_exit(mon_exit);
410
411 MODULE_LICENSE("GPL");