[PATCH 5/5] msm: rpc: ping modem client driver
Niranjana Vishwanathapura
nvishwan at codeaurora.org
Wed Dec 15 13:54:10 EST 2010
Ping rpc client driver which talks to remote Ping rpc server.
This is a test module to ensure working of rpc clients from kernel.
Signed-off-by: Niranjana Vishwanathapura <nvishwan at codeaurora.org>
---
drivers/misc/Kconfig | 7 +
drivers/misc/Makefile | 1 +
drivers/misc/msm_ping_mdm_rpc_client.c | 268 ++++++++++++++++++++++++++++++++
3 files changed, 276 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/msm_ping_mdm_rpc_client.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 345e79c..f5c9b25 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -467,6 +467,13 @@ config MSM_RPCSERVER_WATCHDOG
help
The dog_keepalive server handles watchdog events.
+config MSM_RPC_PING
+ depends on MSM_ONCRPCROUTER && DEBUG_FS
+ default n
+ bool "MSM rpc ping"
+ help
+ Implements MSM rpc ping test module.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 432ad7f..2f272f6 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_MSM_ONCRPCROUTER) += msm_smd_rpcrouter.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += msm_smd_rpcrouter_device.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += msm_smd_rpcrouter_servers.o
obj-$(CONFIG_MSM_RPCSERVER_WATCHDOG) += msm_rpc_server_dog_keepalive.o
+obj-$(CONFIG_MSM_RPC_PING) += msm_ping_mdm_rpc_client.o
diff --git a/drivers/misc/msm_ping_mdm_rpc_client.c b/drivers/misc/msm_ping_mdm_rpc_client.c
new file mode 100644
index 0000000..cc21b4c
--- /dev/null
+++ b/drivers/misc/msm_ping_mdm_rpc_client.c
@@ -0,0 +1,268 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/*
+ * SMD RPC PING MODEM Driver
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include "msm_rpcrouter.h"
+
+#define PING_MDM_PROG 0x30000081
+#define PING_MDM_VERS 0x00010001
+
+#define PING_MDM_NULL_PROC 0
+#define PING_MDM_REGISTER_DATA_PROC 4
+
+#define PING_MDM_DATA_CB_PROC 1
+#define PING_MDM_CB_PROC 2
+
+static DEFINE_MUTEX(ping_mdm_lock);
+
+struct ping_mdm_data_arg {
+ uint32_t *data;
+ uint32_t size;
+};
+
+struct ping_mdm_data_ret {
+ uint32_t result;
+};
+
+static int ping_mdm_data_register(struct msm_rpc_endpoint *ep,
+ struct ping_mdm_data_arg *arg,
+ struct ping_mdm_data_ret *ret)
+{
+ void *req, *reply;
+ uint32_t *tmp;
+ uint32_t req_size, reply_size;
+ int rc, i;
+
+ mutex_lock(&ping_mdm_lock);
+ req_size = sizeof(struct rpc_request_hdr) +
+ (arg->size * sizeof(uint32_t)) +
+ (2 * sizeof(uint32_t));
+ req = kzalloc(req_size, GFP_KERNEL);
+ if (!req) {
+ mutex_unlock(&ping_mdm_lock);
+ return -ENOMEM;
+ }
+
+ reply_size = sizeof(struct rpc_reply_hdr) + sizeof(uint32_t);
+ reply = kzalloc(reply_size, GFP_KERNEL);
+ if (!reply) {
+ kfree(req);
+ mutex_unlock(&ping_mdm_lock);
+ return -ENOMEM;
+ }
+
+ tmp = req + sizeof(struct rpc_request_hdr);
+ *(tmp++) = cpu_to_be32(arg->size);
+
+ for (i = 0; i < arg->size; i++)
+ *(tmp++) = cpu_to_be32(arg->data[i]);
+
+ *(tmp++) = cpu_to_be32(arg->size);
+
+ rc = msm_rpc_call_reply(ep, PING_MDM_REGISTER_DATA_PROC,
+ req, req_size, reply, reply_size, -1);
+ tmp = reply + sizeof(struct rpc_reply_hdr);
+ if (rc > 0) {
+ rc = 0;
+ ret->result = be32_to_cpu(*tmp);
+ }
+
+ mutex_unlock(&ping_mdm_lock);
+ kfree(req);
+ kfree(reply);
+ return rc;
+}
+
+static int ping_mdm_null(struct msm_rpc_endpoint *ep)
+{
+ int rc;
+ struct rpc_request_hdr req;
+
+ mutex_lock(&ping_mdm_lock);
+ rc = msm_rpc_call(ep, PING_MDM_NULL_PROC, &req, sizeof(req), -1);
+ mutex_unlock(&ping_mdm_lock);
+ return rc;
+}
+
+static int ping_mdm_close(struct msm_rpc_endpoint *ep)
+{
+ mutex_lock(&ping_mdm_lock);
+ msm_rpc_close(ep);
+ mutex_unlock(&ping_mdm_lock);
+
+ pr_info("disconnected from remote ping server\n");
+ return 0;
+}
+
+static struct msm_rpc_endpoint *ping_mdm_init(void)
+{
+ struct msm_rpc_endpoint *ep;
+
+ mutex_lock(&ping_mdm_lock);
+ ep = msm_rpc_connect(PING_MDM_PROG, PING_MDM_VERS, 0);
+ mutex_unlock(&ping_mdm_lock);
+ return ep;
+}
+
+#define PING_TEST_DATA_REG_BUF_SIZE 64
+#define PING_TEST_CMD_BUF_SIZE 64
+
+static struct dentry *dent;
+static int32_t test_res;
+struct msm_rpc_endpoint *endpoint;
+
+static int ping_mdm_data_register_test(void)
+{
+ int i, rc = 0;
+ uint32_t my_data[PING_TEST_DATA_REG_BUF_SIZE];
+ uint32_t my_sum = 0;
+ struct ping_mdm_data_arg data_arg;
+ struct ping_mdm_data_ret data_ret;
+
+ for (i = 0; i < PING_TEST_DATA_REG_BUF_SIZE; i++) {
+ my_data[i] = (42 + i);
+ my_sum ^= (42 + i);
+ }
+
+ data_arg.data = my_data;
+ data_arg.size = PING_TEST_DATA_REG_BUF_SIZE;
+ data_ret.result = 0;
+
+ rc = ping_mdm_data_register(endpoint, &data_arg, &data_ret);
+ if (rc)
+ return rc;
+
+ if (my_sum != data_ret.result) {
+ pr_err("sum mismatch %d %d\n", my_sum, data_ret.result);
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static int ping_mdm_null_test(void)
+{
+ return ping_mdm_null(endpoint);
+}
+
+static int ping_test_release(struct inode *ip, struct file *fp)
+{
+ return ping_mdm_close(endpoint);
+}
+
+static int ping_test_open(struct inode *ip, struct file *fp)
+{
+ int rc = 0;
+
+ endpoint = ping_mdm_init();
+ if (IS_ERR(endpoint)) {
+ pr_err("couldn't open ping client\n");
+ rc = PTR_ERR(endpoint);
+ } else
+ pr_info("connected to remote ping server\n");
+
+ return rc;
+}
+
+static ssize_t ping_test_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ char _buf[16];
+
+ snprintf(_buf, sizeof(_buf), "%i\n", test_res);
+
+ return simple_read_from_buffer(buf, count, pos, _buf, strlen(_buf));
+}
+
+static ssize_t ping_test_write(struct file *fp, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ unsigned char cmd[PING_TEST_CMD_BUF_SIZE];
+ int len;
+
+ if (count < 1)
+ return 0;
+
+ len = count > (PING_TEST_CMD_BUF_SIZE - 1) ?
+ (PING_TEST_CMD_BUF_SIZE - 1) : count;
+
+ if (copy_from_user(cmd, buf, len))
+ return -EFAULT;
+
+ cmd[len] = 0;
+
+ /* lazy */
+ if (cmd[len-1] == '\n') {
+ cmd[len-1] = 0;
+ len--;
+ }
+
+ if (!strncmp(cmd, "null_test", PING_TEST_CMD_BUF_SIZE))
+ test_res = ping_mdm_null_test();
+ else if (!strncmp(cmd, "data_reg_test", PING_TEST_CMD_BUF_SIZE))
+ test_res = ping_mdm_data_register_test();
+ else
+ test_res = -EINVAL;
+
+ if (test_res >= 0) {
+ test_res = 0;
+ pr_info("test %s passed\n", cmd);
+ } else
+ pr_info("test %s failed %d\n", cmd, test_res);
+
+ return count;
+}
+
+static const struct file_operations debug_ops = {
+ .owner = THIS_MODULE,
+ .open = ping_test_open,
+ .read = ping_test_read,
+ .write = ping_test_write,
+ .release = ping_test_release,
+};
+
+static void __exit ping_test_exit(void)
+{
+ debugfs_remove(dent);
+}
+
+static int __init ping_test_init(void)
+{
+ dent = debugfs_create_file("ping_mdm", 0444, 0, NULL, &debug_ops);
+ test_res = 0;
+ return 0;
+}
+
+module_init(ping_test_init);
+module_exit(ping_test_exit);
+
+MODULE_DESCRIPTION("PING TEST Driver");
+MODULE_LICENSE("GPL v2");
--
1.5.6.3
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
More information about the linux-arm-kernel
mailing list