summaryrefslogtreecommitdiff
path: root/core/utils
diff options
context:
space:
mode:
authorRyan Hsu <ryanhsu@codeaurora.org>2016-04-28 10:20:14 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-06-01 10:49:09 -0700
commitceddceb3916e7c19df84324c7d81e2643779e2c4 (patch)
tree65426f27e3bb0d8b61230bf9adecebc6cb290c74 /core/utils
parent5e2e20529e81962902af3a4b622442a49e7d7037 (diff)
qcacld-3.0: Add support for cnss logger module
qcacld-2.0 to qcacld-3.0 propagation CONFIG_CNSS_LOGGER is introduced to move the logging feature from CLD driver to kernel module. This change will mainly benefit for two things for CLD driver. - To support for dual wifi driver instances and also future plan of moving out the logging thread and buffer management to the kernel module. - While debugging the critical feature that triggers the autoshutdown and SSR, the log buffer in the CLD driver will be lost after the driver restart or unload. The CLD driver will register itself to the cnss logging module and get the radio index as the indentification for rest of the operation. Also the message sent from CLD driver to usespace need to be packed with struct tAniNlHdr; and the hddctx.radio_index need to be filled along with the message, so that usespace can differentiate the message. Change-Id: I7ea6cdefac0916b9d4dd76da175607bf7169a8fa CRs-fixed: 995073
Diffstat (limited to 'core/utils')
-rw-r--r--core/utils/fwlog/dbglog_host.c51
-rw-r--r--core/utils/logging/src/wlan_logging_sock_svc.c36
-rw-r--r--core/utils/nlink/inc/wlan_nlink_common.h6
-rw-r--r--core/utils/nlink/inc/wlan_nlink_srv.h4
-rw-r--r--core/utils/nlink/src/wlan_nlink_srv.c208
-rw-r--r--core/utils/ptt/inc/wlan_ptt_sock_svc.h5
6 files changed, 283 insertions, 27 deletions
diff --git a/core/utils/fwlog/dbglog_host.c b/core/utils/fwlog/dbglog_host.c
index e4c8f1278820..09e5f959e7f3 100644
--- a/core/utils/fwlog/dbglog_host.c
+++ b/core/utils/fwlog/dbglog_host.c
@@ -1608,6 +1608,9 @@ int send_fw_diag_nl_data(const uint8_t *buffer, A_UINT32 len,
struct sk_buff *skb_out;
struct nlmsghdr *nlh;
int res = 0;
+ tAniNlHdr *wnl;
+ int radio;
+ int msg_len;
if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
return -ENODEV;
@@ -1615,15 +1618,25 @@ int send_fw_diag_nl_data(const uint8_t *buffer, A_UINT32 len,
if (nl_srv_is_initialized() != 0)
return -EIO;
+ radio = cds_get_radio_index();
+ if (radio == -EINVAL)
+ return -EIO;
+
if (cds_is_multicast_logging()) {
- skb_out = nlmsg_new(len, 0);
+ msg_len = len + sizeof(radio);
+ skb_out = nlmsg_new(msg_len, GFP_KERNEL);
if (!skb_out) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("Failed to allocate new skb\n"));
return -ENOMEM;
}
- nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG, len, 0);
- memcpy(nlmsg_data(nlh), buffer, len);
+ nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG, msg_len,
+ 0);
+ wnl = (tAniNlHdr *)nlh;
+ wnl->radio = radio;
+
+ /* data buffer offset from nlmsg_hdr + sizeof(int) radio */
+ memcpy(nlmsg_data(nlh) + sizeof(radio), buffer, len);
res = nl_srv_bcast(skb_out);
if (res < 0) {
@@ -1684,6 +1697,8 @@ send_diag_netlink_data(const uint8_t *buffer, A_UINT32 len, A_UINT32 cmd)
int res = 0;
struct dbglog_slot *slot;
size_t slot_len;
+ tAniNlHdr *wnl;
+ int radio;
if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
return -ENODEV;
@@ -1691,10 +1706,15 @@ send_diag_netlink_data(const uint8_t *buffer, A_UINT32 len, A_UINT32 cmd)
if (nl_srv_is_initialized() != 0)
return -EIO;
+ radio = cds_get_radio_index();
+ if (radio == -EINVAL)
+ return -EIO;
+
if (cds_is_multicast_logging()) {
- slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE;
+ slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE +
+ sizeof(radio);
- skb_out = nlmsg_new(slot_len, 0);
+ skb_out = nlmsg_new(slot_len, GFP_KERNEL);
if (!skb_out) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("Failed to allocate new skb\n"));
@@ -1703,7 +1723,10 @@ send_diag_netlink_data(const uint8_t *buffer, A_UINT32 len, A_UINT32 cmd)
nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG,
slot_len, 0);
- slot = (struct dbglog_slot *)nlmsg_data(nlh);
+ wnl = (tAniNlHdr *)nlh;
+ wnl->radio = radio;
+ /* data buffer offset from: nlmsg_hdr + sizeof(int) radio */
+ slot = (struct dbglog_slot *) (nlmsg_data(nlh) + sizeof(radio));
slot->diag_type = cmd;
slot->timestamp = cpu_to_le32(jiffies);
slot->length = cpu_to_le32(len);
@@ -1731,6 +1754,8 @@ dbglog_process_netlink_data(wmi_unified_t wmi_handle, const uint8_t *buffer,
int res = 0;
struct dbglog_slot *slot;
size_t slot_len;
+ tAniNlHdr *wnl;
+ int radio;
if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
return -ENODEV;
@@ -1738,10 +1763,15 @@ dbglog_process_netlink_data(wmi_unified_t wmi_handle, const uint8_t *buffer,
if (nl_srv_is_initialized() != 0)
return -EIO;
+ radio = cds_get_radio_index();
+ if (radio == -EINVAL)
+ return -EIO;
+
if (cds_is_multicast_logging()) {
- slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE;
+ slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE +
+ sizeof(radio);
- skb_out = nlmsg_new(slot_len, 0);
+ skb_out = nlmsg_new(slot_len, GFP_KERNEL);
if (!skb_out) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("Failed to allocate new skb\n"));
@@ -1750,7 +1780,10 @@ dbglog_process_netlink_data(wmi_unified_t wmi_handle, const uint8_t *buffer,
nlh = nlmsg_put(skb_out, 0, 0, WLAN_NL_MSG_CNSS_DIAG,
slot_len, 0);
- slot = (struct dbglog_slot *)nlmsg_data(nlh);
+ wnl = (tAniNlHdr *)nlh;
+ wnl->radio = radio;
+ /* data buffer offset from: nlmsg_hdr + sizeof(int) radio */
+ slot = (struct dbglog_slot *) (nlmsg_data(nlh) + sizeof(radio));
slot->diag_type = (A_UINT32) DIAG_TYPE_FW_DEBUG_MSG;
slot->timestamp = cpu_to_le32(jiffies);
slot->length = cpu_to_le32(len);
diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c
index c0c854f05bd4..b11a6ca38357 100644
--- a/core/utils/logging/src/wlan_logging_sock_svc.c
+++ b/core/utils/logging/src/wlan_logging_sock_svc.c
@@ -253,10 +253,11 @@ static int wlan_queue_logmsg_for_app(void)
#ifdef QCA_WIFI_3_0_ADRASTEA
/**
- * wlan_add_user_log_time_stamp() - add time stamp in WLAN log buffer
+ * wlan_add_user_log_radio_time_stamp() - add radio and time stamp in log buffer
* @tbuf: Pointer to time stamp buffer
* @tbuf_sz: Time buffer size
* @ts: Time stamp value
+ * @radoi: the radio index
*
* For adrastea time stamp is QTIMER raw tick which will be used by cnss_diag
* to convert it into user visible time stamp. In adrstea FW also uses QTIMER
@@ -266,19 +267,22 @@ static int wlan_queue_logmsg_for_app(void)
* For discrete solution e.g rome use system tick and convert it into
* seconds.milli seconds
*/
-static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts)
+static int wlan_add_user_log_radio_time_stamp(char *tbuf, size_t tbuf_sz,
+ uint64_t ts, int radio)
{
int tlen;
- tlen = scnprintf(tbuf, tbuf_sz, "[%s][%llu] ", current->comm, ts);
+ tlen = scnprintf(tbuf, tbuf_sz, "R%d: [%s][%llu] ",
+ radio, current->comm, ts);
return tlen;
}
#else
/**
- * wlan_add_user_log_time_stamp() - add time stamp in WLAN log buffer
+ * wlan_add_user_log_radio_time_stamp() - add radio and time stamp in log buffer
* @tbuf: Pointer to time stamp buffer
* @tbuf_sz: Time buffer size
* @ts: Time stamp value
+ * @radio: the radio index
*
* For adrastea time stamp QTIMER raw tick which will be used by cnss_diag
* to convert it into user visible time stamp
@@ -286,14 +290,15 @@ static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts)
* For discrete solution e.g rome use system tick and convert it into
* seconds.milli seconds
*/
-static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts)
+static int wlan_add_user_log_radio_time_stamp(char *tbuf, size_t tbuf_sz,
+ uint64_t ts, int radio)
{
int tlen;
uint32_t rem;
rem = do_div(ts, QDF_MC_TIMER_TO_SEC_UNIT);
- tlen = scnprintf(tbuf, tbuf_sz, "[%s][%lu.%06lu] ", current->comm,
- (unsigned long) ts, (unsigned long)rem);
+ tlen = scnprintf(tbuf, tbuf_sz, "R%d: [%s][%lu.%06lu] ", radio,
+ current->comm, (unsigned long) ts, (unsigned long)rem);
return tlen;
}
#endif
@@ -309,8 +314,11 @@ int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length)
bool wake_up_thread = false;
unsigned long flags;
uint64_t ts;
+ int radio;
+
+ radio = cds_get_radio_index();
- if (!cds_is_multicast_logging()) {
+ if (!cds_is_multicast_logging() || radio == -EINVAL) {
/*
* This is to make sure that we print the logs to kmsg console
* when no logger app is running. This is also needed to
@@ -319,12 +327,20 @@ int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length)
* register with driver immediately and start logging all the
* messages.
*/
- pr_info("%s\n", to_be_sent);
+ /*
+ * R%d: if the radio index is invalid, just post the message
+ * to console.
+ * Also the radio index shouldn't happen to be EINVAL, but if
+ * that happen just print it, so that the logging would be
+ * aware the cnss_logger is somehow failed.
+ */
+ pr_info("R%d: %s\n", radio, to_be_sent);
return 0;
}
ts = qdf_get_log_timestamp();
- tlen = wlan_add_user_log_time_stamp(tbuf, sizeof(tbuf), ts);
+ tlen = wlan_add_user_log_radio_time_stamp(tbuf, sizeof(tbuf), ts,
+ radio);
/* 1+1 indicate '\n'+'\0' */
total_log_len = length + tlen + 1 + 1;
diff --git a/core/utils/nlink/inc/wlan_nlink_common.h b/core/utils/nlink/inc/wlan_nlink_common.h
index 1120016d7a97..f714d1bd6aa7 100644
--- a/core/utils/nlink/inc/wlan_nlink_common.h
+++ b/core/utils/nlink/inc/wlan_nlink_common.h
@@ -108,6 +108,12 @@ typedef struct sAniHdr {
unsigned short length;
} tAniHdr, tAniMsgHdr;
+typedef struct sAniNlMsg {
+ struct nlmsghdr nlh; /* Netlink Header */
+ int radio; /* unit number of the radio */
+ tAniHdr wmsg; /* Airgo Message Header */
+} tAniNlHdr;
+
struct wlan_status_data {
uint8_t lpss_support;
uint8_t is_on;
diff --git a/core/utils/nlink/inc/wlan_nlink_srv.h b/core/utils/nlink/inc/wlan_nlink_srv.h
index a973a7b1bfe2..b455b64d583f 100644
--- a/core/utils/nlink/inc/wlan_nlink_srv.h
+++ b/core/utils/nlink/inc/wlan_nlink_srv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -49,7 +49,7 @@
typedef int (*nl_srv_msg_callback)(struct sk_buff *skb);
-int nl_srv_init(void);
+int nl_srv_init(void *wiphy);
void nl_srv_exit(void);
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
int nl_srv_unregister(tWlanNlModTypes msg_type,
diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c
index d3b56faef10b..49bc0812a61a 100644
--- a/core/utils/nlink/src/wlan_nlink_srv.c
+++ b/core/utils/nlink/src/wlan_nlink_srv.c
@@ -43,6 +43,210 @@
#include <wlan_nlink_srv.h>
#include <qdf_trace.h>
+#if defined(CONFIG_CNSS_LOGGER)
+
+#include <net/cnss_logger.h>
+
+static int radio_idx = -EINVAL;
+static void *wiphy_ptr;
+static bool logger_initialized;
+
+/**
+ * nl_srv_init() - wrapper function to register to cnss_logger
+ * @wiphy: the pointer to the wiphy structure
+ *
+ * The netlink socket is no longer initialized in the driver itself, instead
+ * will be initialized in the cnss_logger module, the driver should register
+ * itself to cnss_logger module to get the radio_index for all the netlink
+ * operation. (cfg80211 vendor command is using different netlink socket).
+ *
+ * The cnss_logger_device_register() use to register the driver with the
+ * wiphy structure and the module name (debug purpose) and then return the
+ * radio_index depending on the availibility.
+ *
+ * Return: radio index for success and -EINVAL for failure
+ */
+int nl_srv_init(void *wiphy)
+{
+ if (logger_initialized)
+ goto initialized;
+
+ wiphy_ptr = wiphy;
+ radio_idx = cnss_logger_device_register(wiphy, THIS_MODULE->name);
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR
+ "%s: radio_index: %d, wiphy_ptr: %p",
+ __func__, radio_idx, wiphy_ptr);
+
+ if (radio_idx >= 0)
+ logger_initialized = true;
+
+initialized:
+ return radio_idx;
+}
+
+/**
+ * nl_srv_exit() - wrapper function to unregister from cnss_logger
+ *
+ * The cnss_logger_device_unregister() use to unregister the driver with
+ * the radio_index assigned and wiphy structure from cnss_logger.
+ *
+ * Return: None
+ */
+void nl_srv_exit(void)
+{
+ if (logger_initialized) {
+ cnss_logger_device_unregister(radio_idx, wiphy_ptr);
+ radio_idx = -EINVAL;
+ wiphy_ptr = NULL;
+ logger_initialized = false;
+ }
+}
+
+/**
+ * nl_srv_ucast() - wrapper function to do unicast tx through cnss_logger
+ * @skb: the socket buffer to send
+ * @dst_pid: the port id
+ * @flag: the blocking or nonblocking flag
+ *
+ * The nl_srv_is_initialized() is used to do sanity check if the netlink
+ * service is ready, e.g if the radio_index is assigned properly, if not
+ * the driver should take the responsibility to free the skb.
+ *
+ * The cnss_logger_nl_ucast() use the same parameters to send the socket
+ * buffers.
+ *
+ * Return: the error of the transmission status
+ */
+int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
+{
+ int err = -EINVAL;
+
+ /* sender's pid */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
+ NETLINK_CB(skb).pid = 0;
+#else
+ NETLINK_CB(skb).portid = 0;
+#endif
+ /* not multicast */
+ NETLINK_CB(skb).dst_group = 0;
+
+ if (nl_srv_is_initialized() == 0)
+ err = cnss_logger_nl_ucast(skb, dst_pid, flag);
+ else
+ dev_kfree_skb(skb);
+ return err;
+}
+
+/**
+ * nl_srv_bcast() - wrapper function to do broadcast tx through cnss_logger
+ * @skb: the socket buffer to send
+ *
+ * The cnss_logger_nl_bcast() is used to transmit the socket buffer.
+ *
+ * Return: status of transmission
+ */
+int nl_srv_bcast(struct sk_buff *skb)
+{
+ int err = -EINVAL;
+ int flags = GFP_KERNEL;
+
+ if (in_interrupt() || irqs_disabled() || in_atomic())
+ flags = GFP_ATOMIC;
+
+ /* sender's pid */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
+ NETLINK_CB(skb).pid = 0;
+#else
+ NETLINK_CB(skb).portid = 0;
+#endif
+ /* destination group */
+ NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
+
+ if (nl_srv_is_initialized() == 0)
+ err = cnss_logger_nl_bcast(skb, WLAN_NLINK_MCAST_GRP_ID, flags);
+ else
+ dev_kfree_skb(skb);
+ return err;
+}
+
+/**
+ * nl_srv_unregister() - wrapper function to unregister event to cnss_logger
+ * @msg_type: the message to unregister
+ * @msg_handler: the message handler
+ *
+ * The cnss_logger_event_unregister() is used to unregister the message and
+ * message handler.
+ *
+ * Return: 0 if successfully unregister, otherwise proper error code
+ */
+int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
+{
+ int ret = -EINVAL;
+
+ if (nl_srv_is_initialized() != 0)
+ return ret;
+
+ if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
+ msg_handler != NULL) {
+ ret = cnss_logger_event_unregister(radio_idx, msg_type,
+ msg_handler);
+ } else {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "NLINK: nl_srv_unregister failed for msg_type %d",
+ msg_type);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * nl_srv_register() - wrapper function to register event to cnss_logger
+ * @msg_type: the message to register
+ * @msg_handler: the message handler
+ *
+ * The cnss_logger_event_register() is used to register the message and
+ * message handler.
+ *
+ * Return: 0 if successfully register, otherwise proper error code
+ */
+int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
+{
+ int ret = -EINVAL;
+
+ if (nl_srv_is_initialized() != 0)
+ return ret;
+
+ if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
+ msg_handler != NULL) {
+ ret = cnss_logger_event_register(radio_idx, msg_type,
+ msg_handler);
+ } else {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "NLINK: nl_srv_register failed for msg_type %d",
+ msg_type);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * nl_srv_is_initialized() - check if netlink service is initialized
+ *
+ * Return: 0 if it is initialized, otherwise error code
+ */
+inline int nl_srv_is_initialized(void)
+{
+ if (logger_initialized)
+ return 0;
+ else
+ return -EPERM;
+}
+
+#else
+
+
/* Global variables */
static DEFINE_MUTEX(nl_srv_sem);
static struct sock *nl_srv_sock;
@@ -57,7 +261,7 @@ static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
* Initialize the netlink service.
* Netlink service is usable after this.
*/
-int nl_srv_init(void)
+int nl_srv_init(void *wiphy)
{
int retcode = 0;
struct netlink_kernel_cfg cfg = {
@@ -286,3 +490,5 @@ int nl_srv_is_initialized(void)
return -EPERM;
}
+
+#endif
diff --git a/core/utils/ptt/inc/wlan_ptt_sock_svc.h b/core/utils/ptt/inc/wlan_ptt_sock_svc.h
index 08c149053446..44587480e7ac 100644
--- a/core/utils/ptt/inc/wlan_ptt_sock_svc.h
+++ b/core/utils/ptt/inc/wlan_ptt_sock_svc.h
@@ -115,11 +115,6 @@ static inline int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio,
* WLAN Driver, in either direction. Each msg will begin with this header and
* will followed by the Quarky message
*/
-typedef struct sAniNlMsg {
- struct nlmsghdr nlh; /* Netlink Header */
- int radio; /* unit number of the radio */
- tAniHdr wmsg; /* Airgo Message Header */
-} tAniNlHdr;
typedef struct sAniAppRegReq {
tAniNlModTypes type; /* module id */
int pid; /* process id */