Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20-rc3 410 lines 8.9 kB view raw
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 20static void mon_submit(struct usb_bus *ubus, struct urb *urb); 21static void mon_complete(struct usb_bus *ubus, struct urb *urb); 22static void mon_stop(struct mon_bus *mbus); 23static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); 24static void mon_bus_drop(struct kref *r); 25static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus); 26 27DEFINE_MUTEX(mon_lock); 28 29static struct dentry *mon_dir; /* /dbg/usbmon */ 30static 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 */ 37void 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 */ 69void 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 */ 85static 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 109out_locked: 110 spin_unlock_irqrestore(&mbus->lock, flags); 111out_unlocked: 112 return; 113} 114 115/* 116 */ 117static 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 141out_locked: 142 spin_unlock_irqrestore(&mbus->lock, flags); 143out_unlocked: 144 return; 145} 146 147/* 148 */ 149static 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 */ 181static 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 */ 201static 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 */ 209static 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 223static 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 236static struct notifier_block mon_nb = { 237 .notifier_call = mon_notify, 238}; 239 240/* 241 * Ops 242 */ 243static 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 */ 252static 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 */ 272static 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 */ 284static 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 mbus->uses_dma = ubus->uses_dma; 305 306 rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); 307 if (rc <= 0 || rc >= NAMESZ) 308 goto err_print_t; 309 d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text); 310 if (d == NULL) 311 goto err_create_t; 312 mbus->dent_t = d; 313 314 rc = snprintf(name, NAMESZ, "%ds", ubus->busnum); 315 if (rc <= 0 || rc >= NAMESZ) 316 goto err_print_s; 317 d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat); 318 if (d == NULL) 319 goto err_create_s; 320 mbus->dent_s = d; 321 322 mutex_lock(&mon_lock); 323 list_add_tail(&mbus->bus_link, &mon_buses); 324 mutex_unlock(&mon_lock); 325 return; 326 327err_create_s: 328err_print_s: 329 debugfs_remove(mbus->dent_t); 330err_create_t: 331err_print_t: 332 kfree(mbus); 333err_alloc: 334 return; 335} 336 337static int __init mon_init(void) 338{ 339 struct usb_bus *ubus; 340 struct dentry *mondir; 341 342 mondir = debugfs_create_dir("usbmon", NULL); 343 if (IS_ERR(mondir)) { 344 printk(KERN_NOTICE TAG ": debugfs is not available\n"); 345 return -ENODEV; 346 } 347 if (mondir == NULL) { 348 printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); 349 return -ENODEV; 350 } 351 mon_dir = mondir; 352 353 if (usb_mon_register(&mon_ops_0) != 0) { 354 printk(KERN_NOTICE TAG ": unable to register with the core\n"); 355 debugfs_remove(mondir); 356 return -ENODEV; 357 } 358 // MOD_INC_USE_COUNT(which_module?); 359 360 usb_register_notify(&mon_nb); 361 362 mutex_lock(&usb_bus_list_lock); 363 list_for_each_entry (ubus, &usb_bus_list, bus_list) { 364 mon_bus_init(mondir, ubus); 365 } 366 mutex_unlock(&usb_bus_list_lock); 367 return 0; 368} 369 370static void __exit mon_exit(void) 371{ 372 struct mon_bus *mbus; 373 struct list_head *p; 374 375 usb_unregister_notify(&mon_nb); 376 usb_mon_deregister(); 377 378 mutex_lock(&mon_lock); 379 while (!list_empty(&mon_buses)) { 380 p = mon_buses.next; 381 mbus = list_entry(p, struct mon_bus, bus_link); 382 list_del(p); 383 384 debugfs_remove(mbus->dent_t); 385 debugfs_remove(mbus->dent_s); 386 387 /* 388 * This never happens, because the open/close paths in 389 * file level maintain module use counters and so rmmod fails 390 * before reaching here. However, better be safe... 391 */ 392 if (mbus->nreaders) { 393 printk(KERN_ERR TAG 394 ": Outstanding opens (%d) on usb%d, leaking...\n", 395 mbus->nreaders, mbus->u_bus->busnum); 396 atomic_set(&mbus->ref.refcount, 2); /* Force leak */ 397 } 398 399 mon_dissolve(mbus, mbus->u_bus); 400 kref_put(&mbus->ref, mon_bus_drop); 401 } 402 mutex_unlock(&mon_lock); 403 404 debugfs_remove(mon_dir); 405} 406 407module_init(mon_init); 408module_exit(mon_exit); 409 410MODULE_LICENSE("GPL");