[processor-sdk/open-amp.git] / apps / samples / master / 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 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/rpmsg.h>
19 #include <linux/slab.h>
20 #include <linux/random.h>
22 /* Application */
23 #define MAX_SIZE 6
24 #define NUM_MATRIX 2
25 /* Shutdown message ID */
26 #define SHUTDOWN_MSG 0xEF56A55A
28 struct rpmsg_endpoint *ept;
29 static const char init_msg[] = "init_msg";
31 static const char *const shutdown_argv[]
32 = { "/sbin/shutdown", "-h", "-P", "now", NULL };
34 struct _matrix {
35 unsigned long size;
36 unsigned long elements[MAX_SIZE][MAX_SIZE];
37 };
39 static struct _matrix *p_matrix;
41 static void matrix_print(struct _matrix *m)
42 {
43 int i, j;
45 /* Generate two random matrices */
46 pr_err(" \r\n Master : Linux : Printing results \r\n");
48 for (i = 0; i < m->size; ++i) {
49 for (j = 0; j < m->size; ++j)
50 pr_cont(" %d ", (unsigned int)m->elements[i][j]);
51 pr_info("\r\n");
52 }
53 }
55 static void generate_matrices(int num_matrices, unsigned int matrix_size,
56 void *p_data)
57 {
58 int i, j, k, val;
59 struct _matrix *p_matrix = p_data;
61 /* Generate two random matrices */
62 pr_err(" \r\n Master : Linux : Generating random matrices \r\n");
64 for (i = 0; i < num_matrices; i++) {
66 /* Initialize workload */
67 p_matrix[i].size = matrix_size;
69 pr_err(" \r\n Master : Linux : Input matrix %d \r\n", i);
70 for (j = 0; j < matrix_size; j++) {
72 pr_info("\r\n");
73 for (k = 0; k < matrix_size; k++) {
74 get_random_bytes(&val, sizeof(val));
75 p_matrix[i].elements[j][k] =
76 ((val & 0x7F) % 10);
77 pr_cont(" %d ",
78 (unsigned int)p_matrix[i].elements[j][k]);
79 }
80 }
81 pr_err("\r\n");
82 }
84 }
86 static void rpmsg_mat_mul_kern_app_rx_cb(struct rpmsg_channel *rpdev,
87 void *data, int len, void *priv, u32 src)
88 {
89 int err;
90 int shutdown_msg = SHUTDOWN_MSG;
92 pr_err(" \r\n Master : Linux : Received %d bytes of data", len);
93 pr_err(" over rpmsg channel from remote \r\n");
95 /* Shutdown Linux if such a message is received. Only applicable
96 when Linux is a remoteproc remote. */
97 if ((*(int *) data) == SHUTDOWN_MSG) {
98 call_usermodehelper(shutdown_argv[0], shutdown_argv,
99 NULL, UMH_NO_WAIT);
100 } else {
101 /* print results */
102 matrix_print((struct _matrix *)data);
104 /* Send payload to remote. */
105 err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
106 &shutdown_msg, sizeof(int));
108 if (err)
109 pr_err(" Shutdown send failed!\r\n");
111 kzfree(p_matrix);
112 }
113 }
115 static int rpmsg_mat_mul_kern_app_probe(struct rpmsg_channel *rpdev)
116 {
117 int err;
119 pr_err("\r\n Demo Start - Demo rpmsg driver got probed \r\n");
120 pr_err("since the rpmsg device associated with driver was found !\r\n");
122 pr_err("\r\n Create endpoint and register rx callback \r\n");
123 /* Create endpoint for remote channel and register rx callabck */
124 ept = rpmsg_create_ept(rpdev, rpmsg_mat_mul_kern_app_rx_cb, 0,
125 RPMSG_ADDR_ANY);
127 if (!ept) {
128 pr_err(" Endpoint creation for failed!\r\n");
129 return -ENOMEM;
130 }
132 /* Send init message to complete the connection loop */
133 err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
134 init_msg, sizeof(init_msg));
136 if (err) {
137 pr_err(" Init messages send failed!\r\n");
138 return err;
139 }
141 /* Allocate memory for random matrices */
142 p_matrix = kzalloc(sizeof(struct _matrix)*2, GFP_KERNEL);
144 /* Generate random matrices */
145 generate_matrices(NUM_MATRIX, MAX_SIZE, p_matrix);
147 /* Send matrices to remote for computation */
148 err = rpmsg_send_offchannel(rpdev, ept->addr, rpdev->dst,
149 p_matrix, sizeof(struct _matrix) * 2);
151 pr_err("\r\n Master : Linux : Sent %d bytes of data over rpmsg channel to remote \r\n",
152 sizeof(struct _matrix) * 2);
154 if (err) {
155 pr_err(" send failed!\r\n");
156 return err;
157 }
159 return 0;
160 }
162 static void rpmsg_mat_mul_kern_app_remove(struct rpmsg_channel *rpdev)
163 {
164 rpmsg_destroy_ept(ept);
165 }
167 static void rpmsg_cb(struct rpmsg_channel *rpdev, void *data,
168 int len, void *priv, u32 src)
169 {
171 }
173 static struct rpmsg_device_id rpmsg_mat_mul_kern_app_id_table[] = {
174 { .name = "rpmsg-openamp-demo-channel" },
175 { },
176 };
177 MODULE_DEVICE_TABLE(rpmsg, rpmsg_mat_mul_kern_app_id_table);
179 static struct rpmsg_driver rpmsg_mat_mul_kern_app = {
180 .drv.name = KBUILD_MODNAME,
181 .drv.owner = THIS_MODULE,
182 .id_table = rpmsg_mat_mul_kern_app_id_table,
183 .probe = rpmsg_mat_mul_kern_app_probe,
184 .callback = rpmsg_cb,
185 .remove = rpmsg_mat_mul_kern_app_remove,
186 };
188 static int __init init(void)
189 {
190 return register_rpmsg_driver(&rpmsg_mat_mul_kern_app);
191 }
193 static void __exit fini(void)
194 {
195 unregister_rpmsg_driver(&rpmsg_mat_mul_kern_app);
196 }
198 module_init(init);
199 module_exit(fini);
201 MODULE_DESCRIPTION("Sample rpmsg matrix multiplication kernel application");
202 MODULE_LICENSE("GPL v2");