PageRenderTime 23ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/mailbox/mailbox-test.c

https://github.com/kvaneesh/linux
C | 445 lines | 346 code | 84 blank | 15 comment | 49 complexity | 0ecec5ed25345240c0d05a84f2a826f7 MD5 | raw file
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2015 ST Microelectronics
  4. *
  5. * Author: Lee Jones <lee.jones@linaro.org>
  6. */
  7. #include <linux/debugfs.h>
  8. #include <linux/err.h>
  9. #include <linux/fs.h>
  10. #include <linux/io.h>
  11. #include <linux/kernel.h>
  12. #include <linux/mailbox_client.h>
  13. #include <linux/module.h>
  14. #include <linux/of.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/poll.h>
  17. #include <linux/slab.h>
  18. #include <linux/uaccess.h>
  19. #include <linux/sched/signal.h>
  20. #define MBOX_MAX_SIG_LEN 8
  21. #define MBOX_MAX_MSG_LEN 128
  22. #define MBOX_BYTES_PER_LINE 16
  23. #define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
  24. #define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * \
  25. (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
  26. static bool mbox_data_ready;
  27. struct mbox_test_device {
  28. struct device *dev;
  29. void __iomem *tx_mmio;
  30. void __iomem *rx_mmio;
  31. struct mbox_chan *tx_channel;
  32. struct mbox_chan *rx_channel;
  33. char *rx_buffer;
  34. char *signal;
  35. char *message;
  36. spinlock_t lock;
  37. wait_queue_head_t waitq;
  38. struct fasync_struct *async_queue;
  39. struct dentry *root_debugfs_dir;
  40. };
  41. static ssize_t mbox_test_signal_write(struct file *filp,
  42. const char __user *userbuf,
  43. size_t count, loff_t *ppos)
  44. {
  45. struct mbox_test_device *tdev = filp->private_data;
  46. if (!tdev->tx_channel) {
  47. dev_err(tdev->dev, "Channel cannot do Tx\n");
  48. return -EINVAL;
  49. }
  50. if (count > MBOX_MAX_SIG_LEN) {
  51. dev_err(tdev->dev,
  52. "Signal length %zd greater than max allowed %d\n",
  53. count, MBOX_MAX_SIG_LEN);
  54. return -EINVAL;
  55. }
  56. /* Only allocate memory if we need to */
  57. if (!tdev->signal) {
  58. tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL);
  59. if (!tdev->signal)
  60. return -ENOMEM;
  61. }
  62. if (copy_from_user(tdev->signal, userbuf, count)) {
  63. kfree(tdev->signal);
  64. tdev->signal = NULL;
  65. return -EFAULT;
  66. }
  67. return count;
  68. }
  69. static const struct file_operations mbox_test_signal_ops = {
  70. .write = mbox_test_signal_write,
  71. .open = simple_open,
  72. .llseek = generic_file_llseek,
  73. };
  74. static int mbox_test_message_fasync(int fd, struct file *filp, int on)
  75. {
  76. struct mbox_test_device *tdev = filp->private_data;
  77. return fasync_helper(fd, filp, on, &tdev->async_queue);
  78. }
  79. static ssize_t mbox_test_message_write(struct file *filp,
  80. const char __user *userbuf,
  81. size_t count, loff_t *ppos)
  82. {
  83. struct mbox_test_device *tdev = filp->private_data;
  84. void *data;
  85. int ret;
  86. if (!tdev->tx_channel) {
  87. dev_err(tdev->dev, "Channel cannot do Tx\n");
  88. return -EINVAL;
  89. }
  90. if (count > MBOX_MAX_MSG_LEN) {
  91. dev_err(tdev->dev,
  92. "Message length %zd greater than max allowed %d\n",
  93. count, MBOX_MAX_MSG_LEN);
  94. return -EINVAL;
  95. }
  96. tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
  97. if (!tdev->message)
  98. return -ENOMEM;
  99. ret = copy_from_user(tdev->message, userbuf, count);
  100. if (ret) {
  101. ret = -EFAULT;
  102. goto out;
  103. }
  104. /*
  105. * A separate signal is only of use if there is
  106. * MMIO to subsequently pass the message through
  107. */
  108. if (tdev->tx_mmio && tdev->signal) {
  109. print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS,
  110. tdev->signal, MBOX_MAX_SIG_LEN);
  111. data = tdev->signal;
  112. } else
  113. data = tdev->message;
  114. print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
  115. tdev->message, MBOX_MAX_MSG_LEN);
  116. ret = mbox_send_message(tdev->tx_channel, data);
  117. if (ret < 0)
  118. dev_err(tdev->dev, "Failed to send message via mailbox\n");
  119. out:
  120. kfree(tdev->signal);
  121. kfree(tdev->message);
  122. tdev->signal = NULL;
  123. return ret < 0 ? ret : count;
  124. }
  125. static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
  126. {
  127. bool data_ready;
  128. unsigned long flags;
  129. spin_lock_irqsave(&tdev->lock, flags);
  130. data_ready = mbox_data_ready;
  131. spin_unlock_irqrestore(&tdev->lock, flags);
  132. return data_ready;
  133. }
  134. static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
  135. size_t count, loff_t *ppos)
  136. {
  137. struct mbox_test_device *tdev = filp->private_data;
  138. unsigned long flags;
  139. char *touser, *ptr;
  140. int l = 0;
  141. int ret;
  142. DECLARE_WAITQUEUE(wait, current);
  143. touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
  144. if (!touser)
  145. return -ENOMEM;
  146. if (!tdev->rx_channel) {
  147. ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
  148. ret = simple_read_from_buffer(userbuf, count, ppos,
  149. touser, ret);
  150. goto kfree_err;
  151. }
  152. add_wait_queue(&tdev->waitq, &wait);
  153. do {
  154. __set_current_state(TASK_INTERRUPTIBLE);
  155. if (mbox_test_message_data_ready(tdev))
  156. break;
  157. if (filp->f_flags & O_NONBLOCK) {
  158. ret = -EAGAIN;
  159. goto waitq_err;
  160. }
  161. if (signal_pending(current)) {
  162. ret = -ERESTARTSYS;
  163. goto waitq_err;
  164. }
  165. schedule();
  166. } while (1);
  167. spin_lock_irqsave(&tdev->lock, flags);
  168. ptr = tdev->rx_buffer;
  169. while (l < MBOX_HEXDUMP_MAX_LEN) {
  170. hex_dump_to_buffer(ptr,
  171. MBOX_BYTES_PER_LINE,
  172. MBOX_BYTES_PER_LINE, 1, touser + l,
  173. MBOX_HEXDUMP_LINE_LEN, true);
  174. ptr += MBOX_BYTES_PER_LINE;
  175. l += MBOX_HEXDUMP_LINE_LEN;
  176. *(touser + (l - 1)) = '\n';
  177. }
  178. *(touser + l) = '\0';
  179. memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN);
  180. mbox_data_ready = false;
  181. spin_unlock_irqrestore(&tdev->lock, flags);
  182. ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN);
  183. waitq_err:
  184. __set_current_state(TASK_RUNNING);
  185. remove_wait_queue(&tdev->waitq, &wait);
  186. kfree_err:
  187. kfree(touser);
  188. return ret;
  189. }
  190. static __poll_t
  191. mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
  192. {
  193. struct mbox_test_device *tdev = filp->private_data;
  194. poll_wait(filp, &tdev->waitq, wait);
  195. if (mbox_test_message_data_ready(tdev))
  196. return EPOLLIN | EPOLLRDNORM;
  197. return 0;
  198. }
  199. static const struct file_operations mbox_test_message_ops = {
  200. .write = mbox_test_message_write,
  201. .read = mbox_test_message_read,
  202. .fasync = mbox_test_message_fasync,
  203. .poll = mbox_test_message_poll,
  204. .open = simple_open,
  205. .llseek = generic_file_llseek,
  206. };
  207. static int mbox_test_add_debugfs(struct platform_device *pdev,
  208. struct mbox_test_device *tdev)
  209. {
  210. if (!debugfs_initialized())
  211. return 0;
  212. tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
  213. if (!tdev->root_debugfs_dir) {
  214. dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
  215. return -EINVAL;
  216. }
  217. debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
  218. tdev, &mbox_test_message_ops);
  219. debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
  220. tdev, &mbox_test_signal_ops);
  221. return 0;
  222. }
  223. static void mbox_test_receive_message(struct mbox_client *client, void *message)
  224. {
  225. struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
  226. unsigned long flags;
  227. spin_lock_irqsave(&tdev->lock, flags);
  228. if (tdev->rx_mmio) {
  229. memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN);
  230. print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS,
  231. tdev->rx_buffer, MBOX_MAX_MSG_LEN);
  232. } else if (message) {
  233. print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS,
  234. message, MBOX_MAX_MSG_LEN);
  235. memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
  236. }
  237. mbox_data_ready = true;
  238. spin_unlock_irqrestore(&tdev->lock, flags);
  239. wake_up_interruptible(&tdev->waitq);
  240. kill_fasync(&tdev->async_queue, SIGIO, POLL_IN);
  241. }
  242. static void mbox_test_prepare_message(struct mbox_client *client, void *message)
  243. {
  244. struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
  245. if (tdev->tx_mmio) {
  246. if (tdev->signal)
  247. memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN);
  248. else
  249. memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN);
  250. }
  251. }
  252. static void mbox_test_message_sent(struct mbox_client *client,
  253. void *message, int r)
  254. {
  255. if (r)
  256. dev_warn(client->dev,
  257. "Client: Message could not be sent: %d\n", r);
  258. else
  259. dev_info(client->dev,
  260. "Client: Message sent\n");
  261. }
  262. static struct mbox_chan *
  263. mbox_test_request_channel(struct platform_device *pdev, const char *name)
  264. {
  265. struct mbox_client *client;
  266. struct mbox_chan *channel;
  267. client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
  268. if (!client)
  269. return ERR_PTR(-ENOMEM);
  270. client->dev = &pdev->dev;
  271. client->rx_callback = mbox_test_receive_message;
  272. client->tx_prepare = mbox_test_prepare_message;
  273. client->tx_done = mbox_test_message_sent;
  274. client->tx_block = true;
  275. client->knows_txdone = false;
  276. client->tx_tout = 500;
  277. channel = mbox_request_channel_byname(client, name);
  278. if (IS_ERR(channel)) {
  279. dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
  280. return NULL;
  281. }
  282. return channel;
  283. }
  284. static int mbox_test_probe(struct platform_device *pdev)
  285. {
  286. struct mbox_test_device *tdev;
  287. struct resource *res;
  288. resource_size_t size;
  289. int ret;
  290. tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
  291. if (!tdev)
  292. return -ENOMEM;
  293. /* It's okay for MMIO to be NULL */
  294. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  295. tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
  296. if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
  297. /* if reserved area in SRAM, try just ioremap */
  298. size = resource_size(res);
  299. tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
  300. } else if (IS_ERR(tdev->tx_mmio)) {
  301. tdev->tx_mmio = NULL;
  302. }
  303. /* If specified, second reg entry is Rx MMIO */
  304. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  305. tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
  306. if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
  307. size = resource_size(res);
  308. tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
  309. } else if (IS_ERR(tdev->rx_mmio)) {
  310. tdev->rx_mmio = tdev->tx_mmio;
  311. }
  312. tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
  313. tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
  314. if (!tdev->tx_channel && !tdev->rx_channel)
  315. return -EPROBE_DEFER;
  316. /* If Rx is not specified but has Rx MMIO, then Rx = Tx */
  317. if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio))
  318. tdev->rx_channel = tdev->tx_channel;
  319. tdev->dev = &pdev->dev;
  320. platform_set_drvdata(pdev, tdev);
  321. spin_lock_init(&tdev->lock);
  322. if (tdev->rx_channel) {
  323. tdev->rx_buffer = devm_kzalloc(&pdev->dev,
  324. MBOX_MAX_MSG_LEN, GFP_KERNEL);
  325. if (!tdev->rx_buffer)
  326. return -ENOMEM;
  327. }
  328. ret = mbox_test_add_debugfs(pdev, tdev);
  329. if (ret)
  330. return ret;
  331. init_waitqueue_head(&tdev->waitq);
  332. dev_info(&pdev->dev, "Successfully registered\n");
  333. return 0;
  334. }
  335. static int mbox_test_remove(struct platform_device *pdev)
  336. {
  337. struct mbox_test_device *tdev = platform_get_drvdata(pdev);
  338. debugfs_remove_recursive(tdev->root_debugfs_dir);
  339. if (tdev->tx_channel)
  340. mbox_free_channel(tdev->tx_channel);
  341. if (tdev->rx_channel)
  342. mbox_free_channel(tdev->rx_channel);
  343. return 0;
  344. }
  345. static const struct of_device_id mbox_test_match[] = {
  346. { .compatible = "mailbox-test" },
  347. {},
  348. };
  349. MODULE_DEVICE_TABLE(of, mbox_test_match);
  350. static struct platform_driver mbox_test_driver = {
  351. .driver = {
  352. .name = "mailbox_test",
  353. .of_match_table = mbox_test_match,
  354. },
  355. .probe = mbox_test_probe,
  356. .remove = mbox_test_remove,
  357. };
  358. module_platform_driver(mbox_test_driver);
  359. MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
  360. MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
  361. MODULE_LICENSE("GPL v2");