Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f136d386 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: cnss: add CNSS logger service to support advanced CLD logging"

parents b769b045 2584e1ae
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -74,3 +74,5 @@ config BUS_AUTO_SUSPEND
	  during system pm.
	  This config flag controls the feature per target based. The feature
	  requires CNSS driver support.

source "drivers/net/wireless/cnss/logger/Kconfig"
+2 −0
Original line number Diff line number Diff line
@@ -2,4 +2,6 @@

obj-$(CONFIG_CNSS)	+= cnss_pci.o
obj-$(CONFIG_CNSS)	+= cnss_sdio.o
obj-$(CONFIG_CNSS_LOGGER)	+= logger/

obj-$(CONFIG_CNSS)	+= cnss_common.o
+6 −0
Original line number Diff line number Diff line
config CNSS_LOGGER
	tristate "CNSS Logging Service Driver"
	---help---
	  This module adds support for the CNSS Logging Service for CLD
	  driver, including the netlink socket service registration, transmit,
	  event receive.
+6 −0
Original line number Diff line number Diff line
obj-$(CONFIG_CNSS_LOGGER) += logger.o

logger-y += main.o	\
	    nl_service.o

logger-$(CONFIG_DEBUG_FS) += debugfs.o
+134 −0
Original line number Diff line number Diff line
/* Copyright (c) 2016, 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.
 */

#include <linux/module.h>
#include <linux/debugfs.h>

#include "logger.h"

#define CNSS_LOGGER_STATE_DUMP_BUFFER	(2 * 1024) /* 2KB */

static int logger_state_dump_device(struct logger_device *dev, char *buf,
				    int buf_len)
{
	int len = 0;
	struct logger_event_handler *cur;

	len += scnprintf(buf + len, buf_len - len,
			"==============================================\n");

	len += scnprintf(buf + len, buf_len - len,
			"driver [%s] is registered with radio index: %d\n",
			dev->name, dev->radio_idx);

	if (list_empty(&dev->event_list)) {
		len += scnprintf(buf + len, buf_len - len,
				 "No event registered!\n");
		return len;
	}

	list_for_each_entry(cur, &dev->event_list, list) {
		len += scnprintf(buf + len, buf_len - len,
				"\t event %d\n", cur->event);
	}
	len += scnprintf(buf + len, buf_len - len, "\n");

	return len;
}

static int logger_state_dump(struct logger_context *ctx, char *buf, int buf_len)
{
	int len = 0;
	struct logger_device *cur;

	if (list_empty(&ctx->dev_list)) {
		len += scnprintf(buf + len, buf_len - len,
				 "=======================\n");
		len += scnprintf(buf + len, buf_len - len,
				 "No driver registered!\n");
		return 0;
	}

	list_for_each_entry(cur, &ctx->dev_list, list)
		len += logger_state_dump_device(cur, (buf + len), buf_len);

	return 0;
}

static int logger_state_open(struct inode *inode, struct file *file)
{
	struct logger_context *ctx = inode->i_private;
	void *buf;
	int ret;

	mutex_lock(&ctx->con_mutex);

	buf = kmalloc(CNSS_LOGGER_STATE_DUMP_BUFFER, GFP_KERNEL);
	if (!buf) {
		ret = -ENOMEM;
		goto error_unlock;
	}

	ret = logger_state_dump(ctx, buf, CNSS_LOGGER_STATE_DUMP_BUFFER);
	if (ret)
		goto error_free;

	file->private_data = buf;
	mutex_unlock(&ctx->con_mutex);
	return 0;

error_free:
	kfree(buf);

error_unlock:
	mutex_unlock(&ctx->con_mutex);

	return ret;
}

static int logger_state_release(struct inode *inode, struct file *file)
{
	kfree(file->private_data);
	return 0;
}

static ssize_t logger_state_read(struct file *file, char __user *user_buf,
				 size_t count, loff_t *ppos)
{
	const char *buf = file->private_data;
	unsigned int len = strlen(buf);

	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

static const struct file_operations fops_logger_state = {
	.open = logger_state_open,
	.release = logger_state_release,
	.read = logger_state_read,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

void logger_debugfs_init(struct logger_context *ctx)
{
	if (!ctx->debugfs_entry)
		ctx->debugfs_entry = debugfs_create_dir("cnss_logger", NULL);

	debugfs_create_file("state", S_IRUSR, ctx->debugfs_entry, ctx,
			    &fops_logger_state);
}

void logger_debugfs_remove(struct logger_context *ctx)
{
	debugfs_remove(ctx->debugfs_entry);
}
Loading