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

Commit 2a93006b authored by Yuanyuan Liu's avatar Yuanyuan Liu
Browse files

net: cnss_genl: Add snapshot of cnss_genl driver



This is a snapshot of cnss_utils driver and associated files as of
msm-4.14 commit a88aefea65f4
("msm: Add CLD80211_ATTR_META_DATA vendor attribute").

Checkpatch issues are also fixed on top of this commit.

CRs-Fixed: 2375545
Change-Id: Ib9719a0286b5ff227c431732047ccad5a2427bb3
Signed-off-by: default avatarYuanyuan Liu <yuanliu@codeaurora.org>
parent 59b57424
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -144,5 +144,6 @@ config CLD_LL_CORE

source "drivers/net/wireless/cnss2/Kconfig"
source "drivers/net/wireless/cnss_utils/Kconfig"
source "drivers/net/wireless/cnss_genl/Kconfig"

endif # WLAN
+2 −0
Original line number Diff line number Diff line
@@ -35,3 +35,5 @@ obj-$(CONFIG_CNSS2) += cnss2/
obj-$(CONFIG_CNSS_UTILS) += cnss_utils/

obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/

obj-$(CONFIG_CNSS_GENL) += cnss_genl/
+9 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only

config CNSS_GENL
	tristate "CNSS Generic Netlink Socket Driver"
	help
	  This module creates generic netlink family "CLD80211". This can be
	  used by cld driver and userspace utilities to communicate over
	  netlink sockets. This module creates different multicast groups to
	  facilitate the same.
+3 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only

obj-$(CONFIG_CNSS_GENL) := cnss_nl.o
+200 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */

#include <net/genetlink.h>
#include <net/cnss_nl.h>
#include <linux/module.h>

#define CLD80211_GENL_NAME "cld80211"

#define CLD80211_MULTICAST_GROUP_SVC_MSGS       "svc_msgs"
#define CLD80211_MULTICAST_GROUP_HOST_LOGS      "host_logs"
#define CLD80211_MULTICAST_GROUP_FW_LOGS        "fw_logs"
#define CLD80211_MULTICAST_GROUP_PER_PKT_STATS  "per_pkt_stats"
#define CLD80211_MULTICAST_GROUP_DIAG_EVENTS    "diag_events"
#define CLD80211_MULTICAST_GROUP_FATAL_EVENTS   "fatal_events"
#define CLD80211_MULTICAST_GROUP_OEM_MSGS       "oem_msgs"

static const struct genl_multicast_group nl_mcgrps[] = {
	[CLD80211_MCGRP_SVC_MSGS] = { .name =
			CLD80211_MULTICAST_GROUP_SVC_MSGS},
	[CLD80211_MCGRP_HOST_LOGS] = { .name =
			CLD80211_MULTICAST_GROUP_HOST_LOGS},
	[CLD80211_MCGRP_FW_LOGS] = { .name =
			CLD80211_MULTICAST_GROUP_FW_LOGS},
	[CLD80211_MCGRP_PER_PKT_STATS] = { .name =
			CLD80211_MULTICAST_GROUP_PER_PKT_STATS},
	[CLD80211_MCGRP_DIAG_EVENTS] = { .name =
			CLD80211_MULTICAST_GROUP_DIAG_EVENTS},
	[CLD80211_MCGRP_FATAL_EVENTS] = { .name =
			CLD80211_MULTICAST_GROUP_FATAL_EVENTS},
	[CLD80211_MCGRP_OEM_MSGS] = { .name =
			CLD80211_MULTICAST_GROUP_OEM_MSGS},
};

struct cld_ops {
	cld80211_cb cb;
	void *cb_ctx;
};

struct cld80211_nl_data {
	struct cld_ops cld_ops[CLD80211_MAX_COMMANDS];
};

static struct cld80211_nl_data nl_data;

static inline struct cld80211_nl_data *get_local_ctx(void)
{
	return &nl_data;
}

static struct genl_ops nl_ops[CLD80211_MAX_COMMANDS];

/* policy for the attributes */
static const struct nla_policy cld80211_policy[CLD80211_ATTR_MAX + 1] = {
	[CLD80211_ATTR_VENDOR_DATA] = { .type = NLA_NESTED },
	[CLD80211_ATTR_DATA] = { .type = NLA_BINARY,
				 .len = CLD80211_MAX_NL_DATA },
	[CLD80211_ATTR_META_DATA] = { .type = NLA_BINARY,
				 .len = CLD80211_MAX_NL_DATA },
};

static int cld80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
			     struct genl_info *info)
{
	u8 cmd_id = ops->cmd;
	struct cld80211_nl_data *nl = get_local_ctx();

	if (cmd_id < 1 || cmd_id > CLD80211_MAX_COMMANDS) {
		pr_err("CLD80211: Command Not supported: %u\n", cmd_id);
		return -EOPNOTSUPP;
	}
	info->user_ptr[0] = nl->cld_ops[cmd_id - 1].cb;
	info->user_ptr[1] = nl->cld_ops[cmd_id - 1].cb_ctx;

	return 0;
}

/* The netlink family */
static struct genl_family cld80211_fam __ro_after_init = {
	.name = CLD80211_GENL_NAME,
	.hdrsize = 0,			/* no private header */
	.version = 1,			/* no particular meaning now */
	.maxattr = CLD80211_ATTR_MAX,
	.netnsok = true,
	.pre_doit = cld80211_pre_doit,
	.post_doit = NULL,
	.module = THIS_MODULE,
	.ops = nl_ops,
	.n_ops = ARRAY_SIZE(nl_ops),
	.mcgrps = nl_mcgrps,
	.n_mcgrps = ARRAY_SIZE(nl_mcgrps),
};

int register_cld_cmd_cb(u8 cmd_id, cld80211_cb func, void *cb_ctx)
{
	struct cld80211_nl_data *nl = get_local_ctx();

	pr_debug("CLD80211: Registering command: %d\n", cmd_id);
	if (!cmd_id || cmd_id > CLD80211_MAX_COMMANDS) {
		pr_debug("CLD80211: invalid command: %d\n", cmd_id);
		return -EINVAL;
	}

	nl->cld_ops[cmd_id - 1].cb = func;
	nl->cld_ops[cmd_id - 1].cb_ctx = cb_ctx;

	return 0;
}
EXPORT_SYMBOL(register_cld_cmd_cb);

int deregister_cld_cmd_cb(u8 cmd_id)
{
	struct cld80211_nl_data *nl = get_local_ctx();

	pr_debug("CLD80211: De-registering command: %d\n", cmd_id);
	if (!cmd_id || cmd_id > CLD80211_MAX_COMMANDS) {
		pr_debug("CLD80211: invalid command: %d\n", cmd_id);
		return -EINVAL;
	}

	nl->cld_ops[cmd_id - 1].cb = NULL;
	nl->cld_ops[cmd_id - 1].cb_ctx = NULL;

	return 0;
}
EXPORT_SYMBOL(deregister_cld_cmd_cb);

struct genl_family *cld80211_get_genl_family(void)
{
	return &cld80211_fam;
}
EXPORT_SYMBOL(cld80211_get_genl_family);

static int cld80211_doit(struct sk_buff *skb, struct genl_info *info)
{
	cld80211_cb cld_cb;
	void *cld_ctx;

	cld_cb = info->user_ptr[0];

	if (!cld_cb) {
		pr_err("CLD80211: Not supported\n");
		return -EOPNOTSUPP;
	}
	cld_ctx = info->user_ptr[1];

	if (info->attrs[CLD80211_ATTR_VENDOR_DATA]) {
		cld_cb(nla_data(info->attrs[CLD80211_ATTR_VENDOR_DATA]),
		       nla_len(info->attrs[CLD80211_ATTR_VENDOR_DATA]),
		       cld_ctx, info->snd_portid);
	} else {
		pr_err("CLD80211: No CLD80211_ATTR_VENDOR_DATA\n");
		return -EINVAL;
	}
	return 0;
}

static int __cld80211_init(void)
{
	int err, i;

	memset(&nl_ops[0], 0, sizeof(nl_ops));

	pr_info("CLD80211: Initializing\n");
	for (i = 0; i < CLD80211_MAX_COMMANDS; i++) {
		nl_ops[i].cmd = i + 1;
		nl_ops[i].doit = cld80211_doit;
		nl_ops[i].flags = GENL_ADMIN_PERM;
		nl_ops[i].policy = cld80211_policy;
	}

	err = genl_register_family(&cld80211_fam);
	if (err) {
		pr_err("CLD80211: Failed to register cld80211 family: %d\n",
		       err);
	}

	return err;
}

static void __cld80211_exit(void)
{
	genl_unregister_family(&cld80211_fam);
}

static int __init cld80211_init(void)
{
	return __cld80211_init();
}

static void __exit cld80211_exit(void)
{
	__cld80211_exit();
}

module_init(cld80211_init);
module_exit(cld80211_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CNSS generic netlink module");
Loading