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

Commit 2584e1ae authored by Ryan Hsu's avatar Ryan Hsu
Browse files

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



This is the new module to add the cnss logging service interface
to support CLD driver advanced logging.

This module will allow the CLD driver to register and return the
radio id, and this radio id will be used to in the transmit and receive
path as the identification.

The module provides the following service.

- verified the CLD driver and event register/unregister
- add netlink ucast/bcast interface
- add debugfs entry to dump device/event information

Change-Id: Ie9871af1c79e26a586b3c9bb063411ef3cefab43
CRs-fixed: 1002566
Signed-off-by: default avatarRyan Hsu <ryanhsu@codeaurora.org>
Signed-off-by: default avatarSarada Prasanna Garnayak <sgarna@codeaurora.org>
parent 626b2bb0
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