common.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /**
  2. * @file common.c
  3. *
  4. * @remark Copyright 2004 Oprofile Authors
  5. * @remark Read the file COPYING
  6. *
  7. * @author Zwane Mwaikambo
  8. */
  9. #include <linux/init.h>
  10. #include <linux/oprofile.h>
  11. #include <linux/errno.h>
  12. #include <linux/sysdev.h>
  13. #include <asm/semaphore.h>
  14. #include "op_counter.h"
  15. #include "op_arm_model.h"
  16. static struct op_arm_model_spec *op_arm_model;
  17. static int op_arm_enabled;
  18. static struct semaphore op_arm_sem;
  19. struct op_counter_config counter_config[OP_MAX_COUNTER];
  20. static int op_arm_create_files(struct super_block *sb, struct dentry *root)
  21. {
  22. unsigned int i;
  23. for (i = 0; i < op_arm_model->num_counters; i++) {
  24. struct dentry *dir;
  25. char buf[2];
  26. snprintf(buf, sizeof buf, "%d", i);
  27. dir = oprofilefs_mkdir(sb, root, buf);
  28. oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
  29. oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
  30. oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
  31. oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
  32. oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
  33. oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
  34. }
  35. return 0;
  36. }
  37. static int op_arm_setup(void)
  38. {
  39. int ret;
  40. spin_lock(&oprofilefs_lock);
  41. ret = op_arm_model->setup_ctrs();
  42. spin_unlock(&oprofilefs_lock);
  43. return ret;
  44. }
  45. static int op_arm_start(void)
  46. {
  47. int ret = -EBUSY;
  48. down(&op_arm_sem);
  49. if (!op_arm_enabled) {
  50. ret = op_arm_model->start();
  51. op_arm_enabled = !ret;
  52. }
  53. up(&op_arm_sem);
  54. return ret;
  55. }
  56. static void op_arm_stop(void)
  57. {
  58. down(&op_arm_sem);
  59. if (op_arm_enabled)
  60. op_arm_model->stop();
  61. op_arm_enabled = 0;
  62. up(&op_arm_sem);
  63. }
  64. #ifdef CONFIG_PM
  65. static int op_arm_suspend(struct sys_device *dev, pm_message_t state)
  66. {
  67. down(&op_arm_sem);
  68. if (op_arm_enabled)
  69. op_arm_model->stop();
  70. up(&op_arm_sem);
  71. return 0;
  72. }
  73. static int op_arm_resume(struct sys_device *dev)
  74. {
  75. down(&op_arm_sem);
  76. if (op_arm_enabled && op_arm_model->start())
  77. op_arm_enabled = 0;
  78. up(&op_arm_sem);
  79. return 0;
  80. }
  81. static struct sysdev_class oprofile_sysclass = {
  82. set_kset_name("oprofile"),
  83. .resume = op_arm_resume,
  84. .suspend = op_arm_suspend,
  85. };
  86. static struct sys_device device_oprofile = {
  87. .id = 0,
  88. .cls = &oprofile_sysclass,
  89. };
  90. static int __init init_driverfs(void)
  91. {
  92. int ret;
  93. if (!(ret = sysdev_class_register(&oprofile_sysclass)))
  94. ret = sysdev_register(&device_oprofile);
  95. return ret;
  96. }
  97. static void exit_driverfs(void)
  98. {
  99. sysdev_unregister(&device_oprofile);
  100. sysdev_class_unregister(&oprofile_sysclass);
  101. }
  102. #else
  103. #define init_driverfs() do { } while (0)
  104. #define exit_driverfs() do { } while (0)
  105. #endif /* CONFIG_PM */
  106. int __init oprofile_arch_init(struct oprofile_operations *ops)
  107. {
  108. struct op_arm_model_spec *spec = NULL;
  109. int ret = -ENODEV;
  110. #ifdef CONFIG_CPU_XSCALE
  111. spec = &op_xscale_spec;
  112. #endif
  113. if (spec) {
  114. init_MUTEX(&op_arm_sem);
  115. ret = spec->init();
  116. if (ret < 0)
  117. return ret;
  118. op_arm_model = spec;
  119. init_driverfs();
  120. ops->create_files = op_arm_create_files;
  121. ops->setup = op_arm_setup;
  122. ops->shutdown = op_arm_stop;
  123. ops->start = op_arm_start;
  124. ops->stop = op_arm_stop;
  125. ops->cpu_type = op_arm_model->name;
  126. ops->backtrace = arm_backtrace;
  127. printk(KERN_INFO "oprofile: using %s\n", spec->name);
  128. }
  129. return ret;
  130. }
  131. void oprofile_arch_exit(void)
  132. {
  133. if (op_arm_model) {
  134. exit_driverfs();
  135. op_arm_model = NULL;
  136. }
  137. }