kapi.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. * kernel API
  3. *
  4. *
  5. * Copyright (C) 2005-2009 Rodolfo Giometti <giometti@linux.it>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. #include <linux/kernel.h>
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/sched.h>
  25. #include <linux/time.h>
  26. #include <linux/spinlock.h>
  27. #include <linux/idr.h>
  28. #include <linux/fs.h>
  29. #include <linux/pps_kernel.h>
  30. #include <linux/slab.h>
  31. /*
  32. * Global variables
  33. */
  34. DEFINE_SPINLOCK(pps_idr_lock);
  35. DEFINE_IDR(pps_idr);
  36. /*
  37. * Local functions
  38. */
  39. static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
  40. {
  41. ts->nsec += offset->nsec;
  42. while (ts->nsec >= NSEC_PER_SEC) {
  43. ts->nsec -= NSEC_PER_SEC;
  44. ts->sec++;
  45. }
  46. while (ts->nsec < 0) {
  47. ts->nsec += NSEC_PER_SEC;
  48. ts->sec--;
  49. }
  50. ts->sec += offset->sec;
  51. }
  52. /*
  53. * Exported functions
  54. */
  55. /* pps_get_source - find a PPS source
  56. * @source: the PPS source ID.
  57. *
  58. * This function is used to find an already registered PPS source into the
  59. * system.
  60. *
  61. * The function returns NULL if found nothing, otherwise it returns a pointer
  62. * to the PPS source data struct (the refcounter is incremented by 1).
  63. */
  64. struct pps_device *pps_get_source(int source)
  65. {
  66. struct pps_device *pps;
  67. unsigned long flags;
  68. spin_lock_irqsave(&pps_idr_lock, flags);
  69. pps = idr_find(&pps_idr, source);
  70. if (pps != NULL)
  71. atomic_inc(&pps->usage);
  72. spin_unlock_irqrestore(&pps_idr_lock, flags);
  73. return pps;
  74. }
  75. /* pps_put_source - free the PPS source data
  76. * @pps: a pointer to the PPS source.
  77. *
  78. * This function is used to free a PPS data struct if its refcount is 0.
  79. */
  80. void pps_put_source(struct pps_device *pps)
  81. {
  82. unsigned long flags;
  83. spin_lock_irqsave(&pps_idr_lock, flags);
  84. BUG_ON(atomic_read(&pps->usage) == 0);
  85. if (!atomic_dec_and_test(&pps->usage)) {
  86. pps = NULL;
  87. goto exit;
  88. }
  89. /* No more reference to the PPS source. We can safely remove the
  90. * PPS data struct.
  91. */
  92. idr_remove(&pps_idr, pps->id);
  93. exit:
  94. spin_unlock_irqrestore(&pps_idr_lock, flags);
  95. kfree(pps);
  96. }
  97. /* pps_register_source - add a PPS source in the system
  98. * @info: the PPS info struct
  99. * @default_params: the default PPS parameters of the new source
  100. *
  101. * This function is used to add a new PPS source in the system. The new
  102. * source is described by info's fields and it will have, as default PPS
  103. * parameters, the ones specified into default_params.
  104. *
  105. * The function returns, in case of success, the PPS source ID.
  106. */
  107. int pps_register_source(struct pps_source_info *info, int default_params)
  108. {
  109. struct pps_device *pps;
  110. int id;
  111. int err;
  112. /* Sanity checks */
  113. if ((info->mode & default_params) != default_params) {
  114. printk(KERN_ERR "pps: %s: unsupported default parameters\n",
  115. info->name);
  116. err = -EINVAL;
  117. goto pps_register_source_exit;
  118. }
  119. if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 &&
  120. info->echo == NULL) {
  121. printk(KERN_ERR "pps: %s: echo function is not defined\n",
  122. info->name);
  123. err = -EINVAL;
  124. goto pps_register_source_exit;
  125. }
  126. if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
  127. printk(KERN_ERR "pps: %s: unspecified time format\n",
  128. info->name);
  129. err = -EINVAL;
  130. goto pps_register_source_exit;
  131. }
  132. /* Allocate memory for the new PPS source struct */
  133. pps = kzalloc(sizeof(struct pps_device), GFP_KERNEL);
  134. if (pps == NULL) {
  135. err = -ENOMEM;
  136. goto pps_register_source_exit;
  137. }
  138. /* These initializations must be done before calling idr_get_new()
  139. * in order to avoid reces into pps_event().
  140. */
  141. pps->params.api_version = PPS_API_VERS;
  142. pps->params.mode = default_params;
  143. pps->info = *info;
  144. init_waitqueue_head(&pps->queue);
  145. spin_lock_init(&pps->lock);
  146. atomic_set(&pps->usage, 1);
  147. /* Get new ID for the new PPS source */
  148. if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) {
  149. err = -ENOMEM;
  150. goto kfree_pps;
  151. }
  152. spin_lock_irq(&pps_idr_lock);
  153. /* Now really allocate the PPS source.
  154. * After idr_get_new() calling the new source will be freely available
  155. * into the kernel.
  156. */
  157. err = idr_get_new(&pps_idr, pps, &id);
  158. if (err < 0) {
  159. spin_unlock_irq(&pps_idr_lock);
  160. goto kfree_pps;
  161. }
  162. id = id & MAX_ID_MASK;
  163. if (id >= PPS_MAX_SOURCES) {
  164. spin_unlock_irq(&pps_idr_lock);
  165. printk(KERN_ERR "pps: %s: too many PPS sources in the system\n",
  166. info->name);
  167. err = -EBUSY;
  168. goto free_idr;
  169. }
  170. pps->id = id;
  171. spin_unlock_irq(&pps_idr_lock);
  172. /* Create the char device */
  173. err = pps_register_cdev(pps);
  174. if (err < 0) {
  175. printk(KERN_ERR "pps: %s: unable to create char device\n",
  176. info->name);
  177. goto free_idr;
  178. }
  179. pr_info("new PPS source %s at ID %d\n", info->name, id);
  180. return id;
  181. free_idr:
  182. spin_lock_irq(&pps_idr_lock);
  183. idr_remove(&pps_idr, id);
  184. spin_unlock_irq(&pps_idr_lock);
  185. kfree_pps:
  186. kfree(pps);
  187. pps_register_source_exit:
  188. printk(KERN_ERR "pps: %s: unable to register source\n", info->name);
  189. return err;
  190. }
  191. EXPORT_SYMBOL(pps_register_source);
  192. /* pps_unregister_source - remove a PPS source from the system
  193. * @source: the PPS source ID
  194. *
  195. * This function is used to remove a previously registered PPS source from
  196. * the system.
  197. */
  198. void pps_unregister_source(int source)
  199. {
  200. struct pps_device *pps;
  201. spin_lock_irq(&pps_idr_lock);
  202. pps = idr_find(&pps_idr, source);
  203. if (!pps) {
  204. BUG();
  205. spin_unlock_irq(&pps_idr_lock);
  206. return;
  207. }
  208. spin_unlock_irq(&pps_idr_lock);
  209. pps_unregister_cdev(pps);
  210. pps_put_source(pps);
  211. }
  212. EXPORT_SYMBOL(pps_unregister_source);
  213. /* pps_event - register a PPS event into the system
  214. * @source: the PPS source ID
  215. * @ts: the event timestamp
  216. * @event: the event type
  217. * @data: userdef pointer
  218. *
  219. * This function is used by each PPS client in order to register a new
  220. * PPS event into the system (it's usually called inside an IRQ handler).
  221. *
  222. * If an echo function is associated with the PPS source it will be called
  223. * as:
  224. * pps->info.echo(source, event, data);
  225. */
  226. void pps_event(int source, struct pps_event_time *ts, int event, void *data)
  227. {
  228. struct pps_device *pps;
  229. unsigned long flags;
  230. int captured = 0;
  231. struct pps_ktime ts_real;
  232. if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) {
  233. printk(KERN_ERR "pps: unknown event (%x) for source %d\n",
  234. event, source);
  235. return;
  236. }
  237. pps = pps_get_source(source);
  238. if (!pps)
  239. return;
  240. pr_debug("PPS event on source %d at %ld.%09ld\n",
  241. pps->id, ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
  242. timespec_to_pps_ktime(&ts_real, ts->ts_real);
  243. spin_lock_irqsave(&pps->lock, flags);
  244. /* Must call the echo function? */
  245. if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)))
  246. pps->info.echo(source, event, data);
  247. /* Check the event */
  248. pps->current_mode = pps->params.mode;
  249. if ((event & PPS_CAPTUREASSERT) &
  250. (pps->params.mode & PPS_CAPTUREASSERT)) {
  251. /* We have to add an offset? */
  252. if (pps->params.mode & PPS_OFFSETASSERT)
  253. pps_add_offset(&ts_real,
  254. &pps->params.assert_off_tu);
  255. /* Save the time stamp */
  256. pps->assert_tu = ts_real;
  257. pps->assert_sequence++;
  258. pr_debug("capture assert seq #%u for source %d\n",
  259. pps->assert_sequence, source);
  260. captured = ~0;
  261. }
  262. if ((event & PPS_CAPTURECLEAR) &
  263. (pps->params.mode & PPS_CAPTURECLEAR)) {
  264. /* We have to add an offset? */
  265. if (pps->params.mode & PPS_OFFSETCLEAR)
  266. pps_add_offset(&ts_real,
  267. &pps->params.clear_off_tu);
  268. /* Save the time stamp */
  269. pps->clear_tu = ts_real;
  270. pps->clear_sequence++;
  271. pr_debug("capture clear seq #%u for source %d\n",
  272. pps->clear_sequence, source);
  273. captured = ~0;
  274. }
  275. /* Wake up if captured something */
  276. if (captured) {
  277. pps->last_ev++;
  278. wake_up_interruptible_all(&pps->queue);
  279. kill_fasync(&pps->async_queue, SIGIO, POLL_IN);
  280. }
  281. spin_unlock_irqrestore(&pps->lock, flags);
  282. /* Now we can release the PPS source for (possible) deregistration */
  283. pps_put_source(pps);
  284. }
  285. EXPORT_SYMBOL(pps_event);