usbcore: trim down usb_bus structure
[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 }
269
270 /*
271  */
272 static void mon_bus_drop(struct kref *r)
273 {
274         struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
275         kfree(mbus);
276 }
277
278 /*
279  * Initialize a bus for us:
280  *  - allocate mon_bus
281  *  - refcount USB bus struct
282  *  - link
283  */
284 static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
285 {
286         struct dentry *d;
287         struct mon_bus *mbus;
288         enum { NAMESZ = 10 };
289         char name[NAMESZ];
290         int rc;
291
292         if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
293                 goto err_alloc;
294         kref_init(&mbus->ref);
295         spin_lock_init(&mbus->lock);
296         INIT_LIST_HEAD(&mbus->r_list);
297
298         /*
299          * We don't need to take a reference to ubus, because we receive
300          * a notification if the bus is about to be removed.
301          */
302         mbus->u_bus = ubus;
303         ubus->mon_bus = mbus;
304
305         rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
306         if (rc <= 0 || rc >= NAMESZ)
307                 goto err_print_t;
308         d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text);
309         if (d == NULL)
310                 goto err_create_t;
311         mbus->dent_t = d;
312
313         rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
314         if (rc <= 0 || rc >= NAMESZ)
315                 goto err_print_s;
316         d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat);
317         if (d == NULL)
318                 goto err_create_s;
319         mbus->dent_s = d;
320
321         mutex_lock(&mon_lock);
322         list_add_tail(&mbus->bus_link, &mon_buses);
323         mutex_unlock(&mon_lock);
324         return;
325
326 err_create_s:
327 err_print_s:
328         debugfs_remove(mbus->dent_t);
329 err_create_t:
330 err_print_t:
331         kfree(mbus);
332 err_alloc:
333         return;
334 }
335
336 static int __init mon_init(void)
337 {
338         struct usb_bus *ubus;
339         struct dentry *mondir;
340
341         mondir = debugfs_create_dir("usbmon", NULL);
342         if (IS_ERR(mondir)) {
343                 printk(KERN_NOTICE TAG ": debugfs is not available\n");
344                 return -ENODEV;
345         }
346         if (mondir == NULL) {
347                 printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
348                 return -ENODEV;
349         }
350         mon_dir = mondir;
351
352         if (usb_mon_register(&mon_ops_0) != 0) {
353                 printk(KERN_NOTICE TAG ": unable to register with the core\n");
354                 debugfs_remove(mondir);
355                 return -ENODEV;
356         }
357         // MOD_INC_USE_COUNT(which_module?);
358
359         usb_register_notify(&mon_nb);
360
361         mutex_lock(&usb_bus_list_lock);
362         list_for_each_entry (ubus, &usb_bus_list, bus_list) {
363                 mon_bus_init(mondir, ubus);
364         }
365         mutex_unlock(&usb_bus_list_lock);
366         return 0;
367 }
368
369 static void __exit mon_exit(void)
370 {
371         struct mon_bus *mbus;
372         struct list_head *p;
373
374         usb_unregister_notify(&mon_nb);
375         usb_mon_deregister();
376
377         mutex_lock(&mon_lock);
378         while (!list_empty(&mon_buses)) {
379                 p = mon_buses.next;
380                 mbus = list_entry(p, struct mon_bus, bus_link);
381                 list_del(p);
382
383                 debugfs_remove(mbus->dent_t);
384                 debugfs_remove(mbus->dent_s);
385
386                 /*
387                  * This never happens, because the open/close paths in
388                  * file level maintain module use counters and so rmmod fails
389                  * before reaching here. However, better be safe...
390                  */
391                 if (mbus->nreaders) {
392                         printk(KERN_ERR TAG
393                             ": Outstanding opens (%d) on usb%d, leaking...\n",
394                             mbus->nreaders, mbus->u_bus->busnum);
395                         atomic_set(&mbus->ref.refcount, 2);     /* Force leak */
396                 }
397
398                 mon_dissolve(mbus, mbus->u_bus);
399                 kref_put(&mbus->ref, mon_bus_drop);
400         }
401         mutex_unlock(&mon_lock);
402
403         debugfs_remove(mon_dir);
404 }
405
406 module_init(mon_init);
407 module_exit(mon_exit);
408
409 MODULE_LICENSE("GPL");