msm: ipc: Add support for IPC Logging

Enhance IPC Router to log information pertaining to the messages
exchanged between user-space and other systems.

Change-Id: I8ef3e793a85bcdb14c69eb96278ce2ea8a47df96
Signed-off-by: Zaheerulla Meer <zmeer@codeaurora.org>
This commit is contained in:
Zaheerulla Meer 2013-02-21 17:56:18 +05:30 committed by Stephen Boyd
parent 2c96273c8b
commit 72288ac649
1 changed files with 110 additions and 1 deletions

View File

@ -20,6 +20,9 @@
#include <linux/fcntl.h>
#include <linux/gfp.h>
#include <linux/msm_ipc.h>
#include <linux/sched.h>
#include <linux/thread_info.h>
#include <linux/qmi_encdec.h>
#include <asm/string.h>
#include <asm/atomic.h>
@ -27,16 +30,93 @@
#include <net/sock.h>
#include <mach/msm_ipc_router.h>
#include <mach/msm_ipc_logging.h>
#include "ipc_router.h"
#include "msm_ipc_router_security.h"
#define msm_ipc_sk(sk) ((struct msm_ipc_sock *)(sk))
#define msm_ipc_sk_port(sk) ((struct msm_ipc_port *)(msm_ipc_sk(sk)->port))
#define REQ_RESP_IPC_LOG_PAGES 5
#define IND_IPC_LOG_PAGES 5
#define IPC_SEND 1
#define IPC_RECV 2
#define IPC_REQ_RESP_LOG(level, buf...) \
do { \
if (ipc_req_resp_log_txt) { \
ipc_log_string(ipc_req_resp_log_txt, buf); \
} \
} while (0) \
#define IPC_IND_LOG(level, buf...) \
do { \
if (ipc_ind_log_txt) { \
ipc_log_string(ipc_ind_log_txt, buf); \
} \
} while (0) \
static int sockets_enabled;
static struct proto msm_ipc_proto;
static const struct proto_ops msm_ipc_proto_ops;
static void *ipc_req_resp_log_txt;
static void *ipc_ind_log_txt;
/**
* msm_ipc_router_ipc_log() - Pass log data to IPC logging framework
* @tran: Identifies the data to be a receive or send.
* @ipc_buf: Buffer to extract the log data.
* @port_ptr: IPC Router port corresponding to the current log data.
*
* This function builds the data the would be passed on to the IPC logging
* framework. The data that would be passed corresponds to the information
* that is exchanged between the IPC Router and user space modules during
* request/response/indication transactions.
*/
static void msm_ipc_router_ipc_log(uint8_t tran,
struct sk_buff *ipc_buf, struct msm_ipc_port *port_ptr)
{
struct qmi_header *hdr = (struct qmi_header *)ipc_buf->data;
/*
* IPC Logging format is as below:-
* <Name>(Name of the User Space Process):
* <PID> (PID of the user space process) :
* <TID> (TID of the user space thread) :
* <User Space Module>(CLNT or SERV) :
* <Opertaion Type> (Transmit) :
* <Control Flag> (Req/Resp/Ind) :
* <Transaction ID> :
* <Message ID> :
* <Message Length> :
*/
if (ipc_req_resp_log_txt &&
(((uint8_t) hdr->cntl_flag == QMI_REQUEST_CONTROL_FLAG) ||
((uint8_t) hdr->cntl_flag == QMI_RESPONSE_CONTROL_FLAG)) &&
(port_ptr->type == CLIENT_PORT ||
port_ptr->type == SERVER_PORT)) {
IPC_REQ_RESP_LOG(KERN_DEBUG,
"%s %d %d %s %s CF:%x TI:%x MI:%x ML:%x",
current->comm, current->tgid, current->pid,
(port_ptr->type == CLIENT_PORT ? "QCCI" : "QCSI"),
(tran == IPC_RECV ? "RX" :
(tran == IPC_SEND ? "TX" : "ERR")),
(uint8_t)hdr->cntl_flag, hdr->txn_id, hdr->msg_id,
hdr->msg_len);
} else if (ipc_ind_log_txt &&
((uint8_t)hdr->cntl_flag == QMI_INDICATION_CONTROL_FLAG) &&
(port_ptr->type == CLIENT_PORT ||
port_ptr->type == SERVER_PORT)) {
IPC_IND_LOG(KERN_DEBUG,
"%s %d %d %s %s CF:%x TI:%x MI:%x ML:%x",
current->comm, current->tgid, current->pid,
(port_ptr->type == CLIENT_PORT ? "QCCI" : "QCSI"),
(tran == IPC_RECV ? "RX" :
(tran == IPC_SEND ? "TX" : "ERR")),
(uint8_t)hdr->cntl_flag, hdr->txn_id, hdr->msg_id,
hdr->msg_len);
}
}
static struct sk_buff_head *msm_ipc_router_build_msg(unsigned int num_sect,
struct iovec const *msg_sect,
@ -263,6 +343,7 @@ static int msm_ipc_router_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
struct sockaddr_msm_ipc *dest = (struct sockaddr_msm_ipc *)m->msg_name;
struct sk_buff_head *msg;
struct sk_buff *ipc_buf;
int ret;
if (!dest)
@ -284,7 +365,8 @@ static int msm_ipc_router_sendmsg(struct kiocb *iocb, struct socket *sock,
if (port_ptr->type == CLIENT_PORT)
wait_for_irsc_completion();
ipc_buf = skb_peek(msg);
msm_ipc_router_ipc_log(IPC_SEND, ipc_buf, port_ptr);
ret = msm_ipc_router_send_to(port_ptr, msg, &dest->address);
if (ret == (IPC_ROUTER_HDR_SIZE + total_len))
ret = total_len;
@ -300,6 +382,7 @@ static int msm_ipc_router_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sock *sk = sock->sk;
struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
struct sk_buff_head *msg;
struct sk_buff *ipc_buf;
long timeout;
int ret;
@ -344,6 +427,8 @@ static int msm_ipc_router_recvmsg(struct kiocb *iocb, struct socket *sock,
}
ret = msm_ipc_router_extract_msg(m, msg);
ipc_buf = skb_peek(msg);
msm_ipc_router_ipc_log(IPC_RECV, ipc_buf, port_ptr);
msm_ipc_router_release_msg(msg);
msg = NULL;
release_sock(sk);
@ -518,6 +603,29 @@ static struct proto msm_ipc_proto = {
.obj_size = sizeof(struct msm_ipc_sock),
};
/**
* msm_ipc_router_ipc_log_init() - Init function for IPC Logging
*
* Initialize the buffers to be used to provide the log information
* pertaining to the request, response and indication data flow that
* happens between user and kernel spaces.
*/
void msm_ipc_router_ipc_log_init(void)
{
ipc_req_resp_log_txt =
ipc_log_context_create(REQ_RESP_IPC_LOG_PAGES, "req_resp");
if (!ipc_req_resp_log_txt) {
pr_err("%s: Unable to create IPC logging for Req/Resp",
__func__);
}
ipc_ind_log_txt =
ipc_log_context_create(IND_IPC_LOG_PAGES, "indication");
if (!ipc_ind_log_txt) {
pr_err("%s: Unable to create IPC logging for Indications",
__func__);
}
}
int msm_ipc_router_init_sockets(void)
{
int ret;
@ -536,6 +644,7 @@ int msm_ipc_router_init_sockets(void)
}
sockets_enabled = 1;
msm_ipc_router_ipc_log_init();
out_init_sockets:
return ret;
}