seemp: port instrumentation and logging service
Port seemp related instrumentation and logging service to from
msm-4.4 to msm-4.9. This change serves two purposes:
- Enable logging service for API events – logged events are read by
userspace components
- Log relevant kernel events
Change-Id: I6eeadc0cb0033d167dde49703269946c77f2acda
Signed-off-by: Yida Wang <yidaw@codeaurora.org>
diff --git a/drivers/platform/msm/seemp_core/seemp_ringbuf.c b/drivers/platform/msm/seemp_core/seemp_ringbuf.c
new file mode 100644
index 0000000..4558051
--- /dev/null
+++ b/drivers/platform/msm/seemp_core/seemp_ringbuf.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014-2015, 2017, The Linux Foundation. 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.
+ */
+
+#define pr_fmt(fmt) "seemp: %s: " fmt, __func__
+
+#include "seemp_logk.h"
+#include "seemp_ringbuf.h"
+#include "seemp_event_encoder.h"
+
+/*initial function no need to hold ring_lock*/
+int ringbuf_init(struct seemp_logk_dev *sdev)
+{
+ char *buf;
+ unsigned long virt_addr;
+
+ if (kmalloc_flag) {
+ sdev->ring = kmalloc(sdev->ring_sz, GFP_KERNEL);
+ if (sdev->ring == NULL) {
+ pr_err("kmalloc failed, ring_sz= %d\n", sdev->ring_sz);
+ return -ENOMEM;
+ }
+
+ buf = (char *)sdev->ring;
+
+ /*reserve kmalloc memory as pages to make them remapable*/
+ for (virt_addr = (unsigned long)buf;
+ virt_addr < (unsigned long)buf + sdev->ring_sz;
+ virt_addr += PAGE_SIZE) {
+ SetPageReserved(virt_to_page((virt_addr)));
+ }
+ } else {
+ sdev->ring = vmalloc(sdev->ring_sz);
+ if (sdev->ring == NULL) {
+ pr_err("vmalloc failed, ring_sz = %d\n", sdev->ring_sz);
+ return -ENOMEM;
+ }
+ buf = (char *)sdev->ring;
+
+ /*reserve vmalloc memory as pages to make them remapable*/
+ for (virt_addr = (unsigned long)buf;
+ virt_addr < (unsigned long)buf + sdev->ring_sz;
+ virt_addr += PAGE_SIZE) {
+ SetPageReserved(vmalloc_to_page(
+ (unsigned long *) virt_addr));
+ }
+ }
+
+ memset(sdev->ring, 0, sdev->ring_sz);
+
+ sdev->num_tot_blks = (sdev->ring_sz / BLK_SIZE);
+ sdev->num_writers = 0;
+ sdev->write_idx = 0;
+ sdev->read_idx = 0;
+
+ sdev->num_write_avail_blks = sdev->num_tot_blks;
+ /*no. of blocks available for write*/
+ sdev->num_write_in_prog_blks = 0;
+ /*no. of blocks held by writers to perform writes*/
+
+ sdev->num_read_avail_blks = 0;
+ /*no. of blocks ready for read*/
+ sdev->num_read_in_prog_blks = 0;
+ /*no. of blocks held by the reader to perform read*/
+
+ return 0;
+}
+
+void ringbuf_cleanup(struct seemp_logk_dev *sdev)
+{
+ unsigned long virt_addr;
+
+ if (kmalloc_flag) {
+ for (virt_addr = (unsigned long)sdev->ring;
+ virt_addr < (unsigned long)sdev->ring + sdev->ring_sz;
+ virt_addr += PAGE_SIZE) {
+ /*clear all pages*/
+ ClearPageReserved(virt_to_page((unsigned long *)
+ virt_addr));
+ }
+ kfree(sdev->ring);
+ } else {
+ for (virt_addr = (unsigned long)sdev->ring;
+ virt_addr < (unsigned long)sdev->ring + sdev->ring_sz;
+ virt_addr += PAGE_SIZE) {
+ /*clear all pages*/
+ ClearPageReserved(vmalloc_to_page((unsigned long *)
+ virt_addr));
+ }
+ vfree(sdev->ring);
+ }
+}
+
+struct seemp_logk_blk *ringbuf_fetch_wr_block
+ (struct seemp_logk_dev *sdev)
+{
+ struct seemp_logk_blk *blk = NULL;
+ int idx;
+
+ mutex_lock(&sdev->lock);
+ if (sdev->num_write_avail_blks == 0) {
+ idx = -1;
+ mutex_unlock(&sdev->lock);
+ return blk;
+ }
+
+ idx = sdev->write_idx;
+ sdev->write_idx = (sdev->write_idx + 1) % sdev->num_tot_blks;
+ sdev->num_write_avail_blks--;
+ sdev->num_write_in_prog_blks++;
+ sdev->num_writers++;
+
+ blk = &sdev->ring[idx];
+ blk->status = 0x0;
+
+ mutex_unlock(&sdev->lock);
+ return blk;
+}
+
+void ringbuf_finish_writer(struct seemp_logk_dev *sdev,
+ struct seemp_logk_blk *blk)
+{
+ /* Encode seemp parameters in multi-threaded mode (before mutex lock) */
+ encode_seemp_params(blk);
+
+ /*
+ * finish writing...
+ * the calling process will no longer access this block.
+ */
+ mutex_lock(&sdev->lock);
+
+ sdev->num_writers--;
+ sdev->num_write_in_prog_blks--;
+ sdev->num_read_avail_blks++;
+
+ /*wake up any readers*/
+ if (sdev->num_writers == 0)
+ wake_up_interruptible(&sdev->readers_wq);
+
+ mutex_unlock(&sdev->lock);
+}
+
+int ringbuf_count_marked(struct seemp_logk_dev *sdev)
+{
+ int i;
+ unsigned int marked;
+
+ mutex_lock(&sdev->lock);
+ for (marked = 0, i = 0; i < sdev->num_tot_blks; i++)
+ if (sdev->ring[i].status & 0x1)
+ marked++;
+ mutex_unlock(&sdev->lock);
+
+ return marked;
+}