[processor-sdk/open-amp.git] / obsolete / apps / matrix_multiply / system / linux / kernelspace / rpmsg_mat_mul_kern_app / rpmsg_mat_mul_kern_app.c
1 /*
2 * RPMSG Matrix Multiplication Kernel Driver
3 *
4 * Copyright (C) 2014 Mentor Graphics Corporation
5 * Copyright (C) 2015 Xilinx, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/rpmsg.h>
20 #include <linux/slab.h>
21 #include <linux/device.h>
22 #include <linux/mutex.h>
23 #include <linux/uaccess.h>
24 #include <linux/errno.h>
25 #include <linux/random.h>
27 #define MAX_RPMSG_BUFF_SIZE 512
29 #define MATRIX_SIZE 6
30 #define NUM_MATRIX 2
32 /* Shutdown message ID */
33 #define SHUTDOWN_MSG 0xEF56A55A
35 static const char init_msg[] = "init_msg";
37 static const char *const shutdown_argv[]
38 = { "/sbin/shutdown", "-h", "-P", "now", NULL };
40 struct _matrix {
41 unsigned int size;
42 unsigned int elements[MATRIX_SIZE][MATRIX_SIZE];
43 };
45 static struct _matrix p_matrix[NUM_MATRIX];
47 static void matrix_print(struct _matrix *m)
48 {
49 int i, j;
51 /* Generate two random matrices */
52 pr_err(" \r\n Master : Linux : Printing results \r\n");
54 for (i = 0; i < m->size; ++i) {
55 for (j = 0; j < m->size; ++j)
56 pr_cont(" %d ", (unsigned int)m->elements[i][j]);
57 pr_info("\r\n");
58 }
59 }
61 static void generate_matrices(int num_matrices, unsigned int matrix_size,
62 void *p_data)
63 {
64 int i, j, k, val;
65 struct _matrix *p_matrix = p_data;
67 /* Generate two random matrices */
68 pr_err(" \r\n Master : Linux : Generating random matrices \r\n");
70 for (i = 0; i < num_matrices; i++) {
72 /* Initialize workload */
73 p_matrix[i].size = matrix_size;
75 pr_err(" \r\n Master : Linux : Input matrix %d \r\n", i);
76 for (j = 0; j < matrix_size; j++) {
78 pr_info("\r\n");
79 for (k = 0; k < matrix_size; k++) {
80 get_random_bytes(&val, sizeof(val));
81 p_matrix[i].elements[j][k] =
82 ((val & 0x7F) % 10);
83 pr_cont(" %d ",
84 (unsigned int)p_matrix[i].
85 elements[j][k]);
86 }
87 }
88 pr_err("\r\n");
89 }
91 }
93 static void rpmsg_mat_mul_kern_app_cb(struct rpmsg_channel *rpdev, void *data,
94 int len, void *priv, u32 src)
95 {
96 int err = 0;
97 int shutdown_msg = SHUTDOWN_MSG;
99 if (!data) {
100 return;
101 }
103 if ((*(int *)data) == SHUTDOWN_MSG) {
104 /* Shutdown Linux if such a message is received. Only applicable
105 when Linux is a remoteproc remote. */
106 dev_info(&rpdev->dev,
107 "shutdown message is received. Shutting down...\n");
108 call_usermodehelper(shutdown_argv[0], shutdown_argv, NULL,
109 UMH_NO_WAIT);
110 } else {
111 /* print results */
112 matrix_print((struct _matrix *)data);
114 /* Send payload to remote. */
115 err =
116 rpmsg_sendto(rpdev, &shutdown_msg, sizeof(int), rpdev->dst);
118 if (err)
119 pr_err(" Shutdown send failed!\r\n");
120 }
121 }
123 static int rpmsg_mat_mul_kern_app_probe(struct rpmsg_channel *rpdev)
124 {
125 int err = 0;
126 dev_info(&rpdev->dev, "%s", __func__);
128 err = rpmsg_sendto(rpdev, init_msg, sizeof(init_msg), rpdev->dst);
130 if (err) {
131 pr_err(" Init messages send failed!\r\n");
132 return err;
133 }
134 dev_info(&rpdev->dev, "Sent init_msg to target 0x%x.", rpdev->dst);
136 dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
137 rpdev->src, rpdev->dst);
139 /* Generate random matrices */
140 generate_matrices(NUM_MATRIX, MATRIX_SIZE, p_matrix);
142 /* Send matrices to remote for computation */
143 err =
144 rpmsg_sendto(rpdev, p_matrix, sizeof(struct _matrix) * 2,
145 rpdev->dst);
147 pr_info
148 ("\r\n Master : Linux : Sent %d bytes of data over rpmsg channel to remote \r\n",
149 sizeof(struct _matrix) * 2);
151 if (err) {
152 pr_err(" send failed!\r\n");
153 return err;
154 }
155 return 0;
156 }
158 static void rpmsg_mat_mul_kern_app_remove(struct rpmsg_channel *rpdev)
159 {
160 return;
161 }
163 static struct rpmsg_device_id rpmsg_mat_mul_kern_app_id_table[] = {
164 {.name = "rpmsg-openamp-demo-channel"},
165 {},
166 };
168 static struct rpmsg_driver rpmsg_mat_mul_kern_app_drv = {
169 .drv.name = "rpmsg_mat_mul_kern_app",
170 .drv.owner = THIS_MODULE,
171 .id_table = rpmsg_mat_mul_kern_app_id_table,
172 .probe = rpmsg_mat_mul_kern_app_probe,
173 .remove = rpmsg_mat_mul_kern_app_remove,
174 .callback = rpmsg_mat_mul_kern_app_cb,
175 };
177 static int __init init(void)
178 {
179 return register_rpmsg_driver(&rpmsg_mat_mul_kern_app_drv);
180 }
182 static void __exit fini(void)
183 {
184 unregister_rpmsg_driver(&rpmsg_mat_mul_kern_app_drv);
185 }
187 module_init(init);
188 module_exit(fini);
190 MODULE_DESCRIPTION
191 ("Sample driver to exposes rpmsg svcs to userspace via a char device");
192 MODULE_LICENSE("GPL v2");