aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/ftdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'litmus/ftdev.c')
-rw-r--r--litmus/ftdev.c131
1 files changed, 91 insertions, 40 deletions
diff --git a/litmus/ftdev.c b/litmus/ftdev.c
index d68d05c6d7dc..4a4b2e3e56c2 100644
--- a/litmus/ftdev.c
+++ b/litmus/ftdev.c
@@ -310,80 +310,131 @@ struct file_operations ftdev_fops = {
310 .read = ftdev_read, 310 .read = ftdev_read,
311}; 311};
312 312
313 313int ftdev_init( struct ftdev* ftdev, struct module* owner,
314void ftdev_init(struct ftdev* ftdev, struct module* owner, const char* name) 314 const int minor_cnt, const char* name)
315{ 315{
316 int i, error; 316 int i, err;
317
318 BUG_ON(minor_cnt < 1);
319
317 cdev_init(&ftdev->cdev, &ftdev_fops); 320 cdev_init(&ftdev->cdev, &ftdev_fops);
318 ftdev->name = name; 321 ftdev->name = name;
322 ftdev->minor_cnt = minor_cnt;
319 ftdev->cdev.owner = owner; 323 ftdev->cdev.owner = owner;
320 ftdev->cdev.ops = &ftdev_fops; 324 ftdev->cdev.ops = &ftdev_fops;
321 ftdev->minor_cnt = 0; 325 ftdev->alloc = NULL;
322 for (i = 0; i < MAX_FTDEV_MINORS; i++) { 326 ftdev->free = NULL;
327 ftdev->can_open = NULL;
328
329 ftdev->minor = kcalloc(ftdev->minor_cnt, sizeof(*ftdev->minor),
330 GFP_KERNEL);
331 if (!ftdev->minor) {
332 printk(KERN_WARNING "ftdev(%s): Could not allocate memory\n",
333 ftdev->name);
334 err = -ENOMEM;
335 goto err_out;
336 }
337
338 for (i = 0; i < ftdev->minor_cnt; i++) {
323 mutex_init(&ftdev->minor[i].lock); 339 mutex_init(&ftdev->minor[i].lock);
324 ftdev->minor[i].readers = 0; 340 ftdev->minor[i].readers = 0;
325 ftdev->minor[i].buf = NULL; 341 ftdev->minor[i].buf = NULL;
326 ftdev->minor[i].events = NULL; 342 ftdev->minor[i].events = NULL;
327 } 343 }
328 ftdev->alloc = NULL;
329 ftdev->free = NULL;
330 ftdev->can_open = NULL;
331 344
332 ftdev->class = class_create(owner, ftdev->name); 345 ftdev->class = class_create(owner, ftdev->name);
333 if (IS_ERR(ftdev->class)) { 346 if (IS_ERR(ftdev->class)) {
334 error = PTR_ERR(ftdev->class); 347 err = PTR_ERR(ftdev->class);
335 printk(KERN_WARNING "ftdev(%s): " 348 printk(KERN_WARNING "ftdev(%s): "
336 "Could not create device class.\n", 349 "Could not create device class.\n", ftdev->name);
337 name); 350 goto err_dealloc;
338 } 351 }
352
353 return 0;
354
355err_dealloc:
356 kfree(ftdev->minor);
357err_out:
358 return err;
359}
360
361/*
362 * Destroy minor devices up to, but not including, up_to.
363 */
364static void ftdev_device_destroy(struct ftdev* ftdev, unsigned int up_to)
365{
366 dev_t minor_cntr;
367
368 if (up_to < 1)
369 up_to = (ftdev->minor_cnt < 1) ? 0 : ftdev->minor_cnt;
370
371 for (minor_cntr = 0; minor_cntr < up_to; ++minor_cntr)
372 device_destroy(ftdev->class, MKDEV(ftdev->major, minor_cntr));
373}
374
375void ftdev_exit(struct ftdev* ftdev)
376{
377 printk("ftdev(%s): Exiting\n", ftdev->name);
378 ftdev_device_destroy(ftdev, -1);
379 cdev_del(&ftdev->cdev);
380 unregister_chrdev_region(MKDEV(ftdev->major, 0), ftdev->minor_cnt);
381 class_destroy(ftdev->class);
382 kfree(ftdev->minor);
339} 383}
340 384
341int register_ftdev(struct ftdev* ftdev) 385int register_ftdev(struct ftdev* ftdev)
342{ 386{
343 struct device **device; 387 struct device **device;
344 dev_t trace_dev; 388 dev_t trace_dev_tmp, minor_cntr;
345 int error = 0, major, i; 389 int err;
346 390
347 error = alloc_chrdev_region(&trace_dev, 0, ftdev->minor_cnt, 391 err = alloc_chrdev_region(&trace_dev_tmp, 0, ftdev->minor_cnt,
348 ftdev->name); 392 ftdev->name);
349 major = MAJOR(trace_dev); 393 if (err) {
350 if (error)
351 {
352 printk(KERN_WARNING "ftdev(%s): " 394 printk(KERN_WARNING "ftdev(%s): "
353 "Could not register major/minor number %d/%u\n", 395 "Could not allocate char. device region (%d minors)\n",
354 ftdev->name, major, ftdev->minor_cnt); 396 ftdev->name, ftdev->minor_cnt);
355 goto out; 397 goto err_out;
356 } 398 }
357 error = cdev_add(&ftdev->cdev, trace_dev, ftdev->minor_cnt); 399
358 if (error) { 400 ftdev->major = MAJOR(trace_dev_tmp);
401
402 err = cdev_add(&ftdev->cdev, trace_dev_tmp, ftdev->minor_cnt);
403 if (err) {
359 printk(KERN_WARNING "ftdev(%s): " 404 printk(KERN_WARNING "ftdev(%s): "
360 "Could not add cdev for major/minor = %d/%u.\n", 405 "Could not add cdev for major %u with %u minor(s).\n",
361 ftdev->name, major, ftdev->minor_cnt); 406 ftdev->name, ftdev->major, ftdev->minor_cnt);
362 goto out; 407 goto err_unregister;
363 } 408 }
364 409
365 /* 410 /* create the minor device(s) */
366 * create all the minor devices 411 for (minor_cntr = 0; minor_cntr < ftdev->minor_cnt; ++minor_cntr)
367 */
368 for (i = 0; i < ftdev->minor_cnt; ++i)
369 { 412 {
370 trace_dev = MKDEV(major, i); 413 trace_dev_tmp = MKDEV(ftdev->major, minor_cntr);
371 device = &(ftdev->minor[i].device); 414 device = &ftdev->minor[minor_cntr].device;
372 415
373 *device = device_create(ftdev->class, NULL, trace_dev, NULL, 416 *device = device_create(ftdev->class, NULL, trace_dev_tmp, NULL,
374 "%s%d", ftdev->name, i); 417 "litmus/%s%d", ftdev->name, minor_cntr);
375 if (IS_ERR(*device)) { 418 if (IS_ERR(*device)) {
376 error = PTR_ERR(*device); 419 err = PTR_ERR(*device);
377 printk(KERN_WARNING "ftdev(%s): " 420 printk(KERN_WARNING "ftdev(%s): "
378 "Could not create device major/minor number " 421 "Could not create device major/minor number "
379 "%d/%d\n", ftdev->name, major, i); 422 "%u/%u\n", ftdev->name, ftdev->major,
423 minor_cntr);
380 printk(KERN_WARNING "ftdev(%s): " 424 printk(KERN_WARNING "ftdev(%s): "
381 "Will not continue creating devices. Tracing " 425 "will attempt deletion of allocated devices.\n",
382 "may be in an inconsistent state.\n",
383 ftdev->name); 426 ftdev->name);
384 goto out; 427 goto err_minors;
385 } 428 }
386 } 429 }
387out: 430
388 return error; 431 return 0;
432
433err_minors:
434 ftdev_device_destroy(ftdev, minor_cntr);
435 cdev_del(&ftdev->cdev);
436err_unregister:
437 unregister_chrdev_region(MKDEV(ftdev->major, 0), ftdev->minor_cnt);
438err_out:
439 return err;
389} 440}