dev_ril_bridge.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (C) 2017 Samsung Electronics.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/device.h>
  15. #include <linux/sysfs.h>
  16. #include <linux/module.h>
  17. #include <linux/notifier.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/of.h>
  20. #include <linux/of_gpio.h>
  21. #include <linux/of_platform.h>
  22. #include <linux/miscdevice.h>
  23. #include <linux/poll.h>
  24. #include <linux/kernel.h>
  25. #include <linux/slab.h>
  26. #include <linux/skbuff.h>
  27. #include <linux/netdevice.h>
  28. #include <linux/dev_ril_bridge.h>
  29. #define LOG_TAG "drb: "
  30. #define drb_err(fmt, ...) \
  31. pr_err(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__)
  32. #define drb_debug(fmt, ...) \
  33. pr_debug(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__)
  34. #define drb_info(fmt, ...) \
  35. pr_info(LOG_TAG "%s: " pr_fmt(fmt), __func__, ##__VA_ARGS__)
  36. struct drb_dev {
  37. atomic_t opened;
  38. wait_queue_head_t wq;
  39. struct sk_buff_head sk_rx_q;
  40. struct miscdevice miscdev;
  41. };
  42. static struct drb_dev *drb_dev;
  43. int dev_ril_bridge_send_msg(int id, int size, void *buf)
  44. {
  45. struct sk_buff *skb;
  46. struct sk_buff_head *rxq;
  47. struct sipc_fmt_hdr *sipc_hdr;
  48. unsigned int alloc_size;
  49. unsigned int headroom;
  50. drb_info("id=%d size=%d\n", id, size);
  51. if (!drb_dev) {
  52. drb_err("ERR! dev_ril_bridge is not ready\n");
  53. return -ENODEV;
  54. }
  55. rxq = &drb_dev->sk_rx_q;
  56. headroom = sizeof(struct sipc_fmt_hdr);
  57. alloc_size = size + headroom;
  58. skb = alloc_skb(alloc_size, GFP_ATOMIC);
  59. if (!skb) {
  60. drb_err("ERR! alloc_skb fail\n");
  61. return -ENOMEM;
  62. }
  63. skb_reserve(skb, headroom);
  64. memcpy(skb_put(skb, size), buf, size);
  65. sipc_hdr = (struct sipc_fmt_hdr *)skb_push(skb, headroom);
  66. sipc_hdr->len = alloc_size;
  67. sipc_hdr->main_cmd = 0x27;
  68. sipc_hdr->sub_cmd = id;
  69. sipc_hdr->cmd_type = 0x05;
  70. skb_queue_tail(rxq, skb);
  71. if (atomic_read(&drb_dev->opened) > 0)
  72. wake_up(&drb_dev->wq);
  73. else
  74. return -EPIPE;
  75. return 0;
  76. }
  77. EXPORT_SYMBOL_GPL(dev_ril_bridge_send_msg);
  78. static RAW_NOTIFIER_HEAD(dev_ril_bridge_chain);
  79. int register_dev_ril_bridge_event_notifier(struct notifier_block *nb)
  80. {
  81. if (!nb)
  82. return -ENOENT;
  83. return raw_notifier_chain_register(&dev_ril_bridge_chain, nb);
  84. }
  85. EXPORT_SYMBOL_GPL(register_dev_ril_bridge_event_notifier);
  86. int unregister_dev_ril_bridge_event_notifier(struct notifier_block *nb)
  87. {
  88. if (!nb)
  89. return -ENOENT;
  90. return raw_notifier_chain_unregister(&dev_ril_bridge_chain, nb);
  91. }
  92. EXPORT_SYMBOL_GPL(unregister_dev_ril_bridge_event_notifier);
  93. static int misc_open(struct inode *inode, struct file *filp)
  94. {
  95. filp->private_data = (void *)drb_dev;
  96. atomic_inc(&drb_dev->opened);
  97. drb_info("drb (opened %d) by %s\n",
  98. atomic_read(&drb_dev->opened), current->comm);
  99. return 0;
  100. }
  101. static int misc_release(struct inode *inode, struct file *filp)
  102. {
  103. struct drb_dev *drb_dev = (struct drb_dev *)filp->private_data;
  104. if (atomic_dec_and_test(&drb_dev->opened)) {
  105. skb_queue_purge(&drb_dev->sk_rx_q);
  106. }
  107. filp->private_data = NULL;
  108. drb_info("drb (opened %d) by %s\n",
  109. atomic_read(&drb_dev->opened), current->comm);
  110. return 0;
  111. }
  112. static unsigned int misc_poll(struct file *filp, struct poll_table_struct *wait)
  113. {
  114. struct drb_dev *drb_dev = (struct drb_dev *)filp->private_data;
  115. struct sk_buff_head *rxq;
  116. int ret = 0;
  117. if (!drb_dev)
  118. return POLLERR;
  119. rxq = &drb_dev->sk_rx_q;
  120. if (skb_queue_empty(rxq))
  121. poll_wait(filp, &drb_dev->wq, wait);
  122. /* drb_dev was already released by shutdown logic */
  123. if (!drb_dev)
  124. return POLLERR;
  125. if (!skb_queue_empty(rxq))
  126. ret = POLLIN | POLLRDNORM;
  127. drb_info("poll done by %s (%d)\n", current->comm, ret);
  128. return ret;
  129. }
  130. static ssize_t misc_write(struct file *filp, const char __user *data,
  131. size_t count, loff_t *fops)
  132. {
  133. struct dev_ril_bridge_msg msg;
  134. struct sipc_fmt_hdr *sipc_hdr;
  135. char *buf;
  136. if (count <= sizeof(struct sipc_fmt_hdr)) {
  137. drb_err("ERR! too small size data(count %lu)\n",
  138. (unsigned long)count);
  139. return -EFAULT;
  140. }
  141. buf = kmalloc(count, GFP_KERNEL);
  142. if (!buf) {
  143. drb_err("ERR! kmalloc failed\n");
  144. return -ENOMEM;
  145. }
  146. if (copy_from_user(buf, data, count)) {
  147. drb_err("ERR! copy_from_user fail(count %lu)\n",
  148. (unsigned long)count);
  149. kfree(buf);
  150. return -EFAULT;
  151. }
  152. sipc_hdr = (struct sipc_fmt_hdr *)buf;
  153. if (sipc_hdr->main_cmd != 0x27 || sipc_hdr->cmd_type != 0x03) {
  154. drb_err("ERR! wrong cmd(main_cmd=%02x, cmd_type=%02x)\n",
  155. sipc_hdr->main_cmd, sipc_hdr->cmd_type);
  156. kfree(buf);
  157. return -EFAULT;
  158. }
  159. msg.dev_id = sipc_hdr->sub_cmd;
  160. msg.data_len = count - (unsigned int)sizeof(struct sipc_fmt_hdr);
  161. msg.data = (void *)(buf + sizeof(struct sipc_fmt_hdr));
  162. drb_info("notifier_call: dev_id=%u data_len=%u\n", msg.dev_id, msg.data_len);
  163. raw_notifier_call_chain(&dev_ril_bridge_chain,
  164. sizeof(struct dev_ril_bridge_msg), (void *)&msg);
  165. kfree(buf);
  166. return count;
  167. }
  168. static ssize_t misc_read(struct file *filp, char *buf, size_t count,
  169. loff_t *fops)
  170. {
  171. struct drb_dev *drb_dev = (struct drb_dev *)filp->private_data;
  172. struct sk_buff_head *rxq = &drb_dev->sk_rx_q;
  173. unsigned int cnt = (unsigned int)count;
  174. struct sk_buff *skb;
  175. ssize_t copied;
  176. if (skb_queue_empty(rxq)) {
  177. long tmo = msecs_to_jiffies(100);
  178. wait_event_timeout(drb_dev->wq, !skb_queue_empty(rxq), tmo);
  179. }
  180. skb = skb_dequeue(rxq);
  181. if (unlikely(!skb)) {
  182. drb_err("No data in RXQ\n");
  183. return 0;
  184. }
  185. copied = skb->len > cnt ? cnt : skb->len;
  186. if (copy_to_user(buf, skb->data, copied)) {
  187. drb_err("ERR! copy_to_user fail\n");
  188. dev_kfree_skb_any(skb);
  189. return -EFAULT;
  190. }
  191. drb_info("data:%d copied:%ld qlen:%d\n", skb->len, copied, rxq->qlen);
  192. if (skb->len > copied) {
  193. skb_pull(skb, copied);
  194. skb_queue_head(rxq, skb);
  195. } else {
  196. dev_kfree_skb_any(skb);
  197. }
  198. return copied;
  199. }
  200. static const struct file_operations misc_io_fops = {
  201. .owner = THIS_MODULE,
  202. .open = misc_open,
  203. .release = misc_release,
  204. .poll = misc_poll,
  205. .write = misc_write,
  206. .read = misc_read,
  207. };
  208. static int __init dev_ril_bridge_init(void)
  209. {
  210. int err = 0;
  211. drb_info("+++\n");
  212. if (drb_dev != NULL) {
  213. drb_info("already probed\n");
  214. return 0;
  215. }
  216. drb_dev = kzalloc(sizeof(struct drb_dev), GFP_KERNEL);
  217. if (drb_dev == NULL)
  218. return -ENOMEM;
  219. init_waitqueue_head(&drb_dev->wq);
  220. skb_queue_head_init(&drb_dev->sk_rx_q);
  221. drb_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
  222. drb_dev->miscdev.name = "drb";
  223. drb_dev->miscdev.fops = &misc_io_fops;
  224. err = misc_register(&drb_dev->miscdev);
  225. if (err) {
  226. drb_err("misc_register fail\n");
  227. goto out;
  228. }
  229. drb_info("---\n");
  230. return 0;
  231. out:
  232. drb_info("err = %d ---\n", err);
  233. return err;
  234. }
  235. static void __exit dev_ril_bridge_exit(void)
  236. {
  237. drb_info("\n");
  238. }
  239. module_init(dev_ril_bridge_init);
  240. module_exit(dev_ril_bridge_exit);
  241. MODULE_DESCRIPTION("dev_ril_bridge driver");
  242. MODULE_LICENSE("GPL");