Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright Samuel Mendoza-Jonas, IBM Corporation 2018.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <net/ncsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <uapi/linux/ncsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "ncsi-pkt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "ncsi-netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) static struct genl_family ncsi_genl_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) static const struct nla_policy ncsi_genl_policy[NCSI_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	[NCSI_ATTR_IFINDEX] =		{ .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	[NCSI_ATTR_PACKAGE_LIST] =	{ .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	[NCSI_ATTR_PACKAGE_ID] =	{ .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	[NCSI_ATTR_CHANNEL_ID] =	{ .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	[NCSI_ATTR_DATA] =		{ .type = NLA_BINARY, .len = 2048 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	[NCSI_ATTR_MULTI_FLAG] =	{ .type = NLA_FLAG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	[NCSI_ATTR_PACKAGE_MASK] =	{ .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	[NCSI_ATTR_CHANNEL_MASK] =	{ .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static struct ncsi_dev_priv *ndp_from_ifindex(struct net *net, u32 ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct ncsi_dev *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	struct ncsi_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	if (!net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	dev = dev_get_by_index(net, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		pr_err("NCSI netlink: No device for ifindex %u\n", ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	nd = ncsi_find_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	return ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) static int ncsi_write_channel_info(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 				   struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 				   struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct ncsi_channel_vlan_filter *ncf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	struct ncsi_channel_mode *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	struct nlattr *vid_nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	nla_put_u32(skb, NCSI_CHANNEL_ATTR_ID, nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	m = &nc->modes[NCSI_MODE_LINK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	nla_put_u32(skb, NCSI_CHANNEL_ATTR_LINK_STATE, m->data[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (nc->state == NCSI_CHANNEL_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		nla_put_flag(skb, NCSI_CHANNEL_ATTR_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (nc == nc->package->preferred_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		nla_put_flag(skb, NCSI_CHANNEL_ATTR_FORCED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MAJOR, nc->version.version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MINOR, nc->version.alpha2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	nla_put_string(skb, NCSI_CHANNEL_ATTR_VERSION_STR, nc->version.fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	vid_nest = nla_nest_start_noflag(skb, NCSI_CHANNEL_ATTR_VLAN_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (!vid_nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	ncf = &nc->vlan_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	i = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	while ((i = find_next_bit((void *)&ncf->bitmap, ncf->n_vids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 				  i + 1)) < ncf->n_vids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		if (ncf->vids[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			nla_put_u16(skb, NCSI_CHANNEL_ATTR_VLAN_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 				    ncf->vids[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	nla_nest_end(skb, vid_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) static int ncsi_write_package_info(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 				   struct ncsi_dev_priv *ndp, unsigned int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct nlattr *pnest, *cnest, *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	bool found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (id > ndp->package_num - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		netdev_info(ndp->ndev.dev, "NCSI: No package with id %u\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		if (np->id != id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		pnest = nla_nest_start_noflag(skb, NCSI_PKG_ATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		if (!pnest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		rc = nla_put_u32(skb, NCSI_PKG_ATTR_ID, np->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			nla_nest_cancel(skb, pnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		if ((0x1 << np->id) == ndp->package_whitelist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			nla_put_flag(skb, NCSI_PKG_ATTR_FORCED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		cnest = nla_nest_start_noflag(skb, NCSI_PKG_ATTR_CHANNEL_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		if (!cnest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			nla_nest_cancel(skb, pnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			nest = nla_nest_start_noflag(skb, NCSI_CHANNEL_ATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			if (!nest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 				nla_nest_cancel(skb, cnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 				nla_nest_cancel(skb, pnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 				return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			rc = ncsi_write_channel_info(skb, ndp, nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 				nla_nest_cancel(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 				nla_nest_cancel(skb, cnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 				nla_nest_cancel(skb, pnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 				return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		nla_nest_end(skb, cnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		nla_nest_end(skb, pnest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int ncsi_pkg_info_nl(struct sk_buff *msg, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	unsigned int package_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (!info || !info->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	if (!info->attrs[NCSI_ATTR_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (!info->attrs[NCSI_ATTR_PACKAGE_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	ndp = ndp_from_ifindex(genl_info_net(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			       nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			  &ncsi_genl_family, 0, NCSI_CMD_PKG_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	attr = nla_nest_start_noflag(skb, NCSI_ATTR_PACKAGE_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (!attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	rc = ncsi_write_package_info(skb, ndp, package_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		nla_nest_cancel(skb, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	nla_nest_end(skb, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	return genlmsg_reply(skb, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int ncsi_pkg_info_all_nl(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 				struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct nlattr *attrs[NCSI_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	struct ncsi_package *np, *package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	unsigned int package_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	rc = genlmsg_parse_deprecated(cb->nlh, &ncsi_genl_family, attrs, NCSI_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 				      ncsi_genl_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	if (!attrs[NCSI_ATTR_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	ndp = ndp_from_ifindex(get_net(sock_net(skb->sk)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			       nla_get_u32(attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	package_id = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	package = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	NCSI_FOR_EACH_PACKAGE(ndp, np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		if (np->id == package_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			package = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (!package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		return 0; /* done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			  &ncsi_genl_family, NLM_F_MULTI,  NCSI_CMD_PKG_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	attr = nla_nest_start_noflag(skb, NCSI_ATTR_PACKAGE_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	if (!attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	rc = ncsi_write_package_info(skb, ndp, package->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		nla_nest_cancel(skb, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	nla_nest_end(skb, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	cb->args[0] = package_id + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int ncsi_set_interface_nl(struct sk_buff *msg, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	struct ncsi_package *np, *package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	struct ncsi_channel *nc, *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	u32 package_id, channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (!info || !info->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (!info->attrs[NCSI_ATTR_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	if (!info->attrs[NCSI_ATTR_PACKAGE_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			       nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	package = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	NCSI_FOR_EACH_PACKAGE(ndp, np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		if (np->id == package_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			package = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	if (!package) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		/* The user has set a package that does not exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	if (info->attrs[NCSI_ATTR_CHANNEL_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		NCSI_FOR_EACH_CHANNEL(package, nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			if (nc->id == channel_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 				channel = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		if (!channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			netdev_info(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 				    "NCSI: Channel %u does not exist!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 				    channel_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	ndp->package_whitelist = 0x1 << package->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	ndp->multi_package = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	spin_lock_irqsave(&package->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	package->multi_channel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		package->channel_whitelist = 0x1 << channel->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		package->preferred_channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		/* Allow any channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		package->channel_whitelist = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		package->preferred_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	spin_unlock_irqrestore(&package->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		netdev_info(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			    "Set package 0x%x, channel 0x%x as preferred\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			    package_id, channel_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		netdev_info(ndp->ndev.dev, "Set package 0x%x as preferred\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			    package_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	/* Update channel configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	if (!(ndp->flags & NCSI_DEV_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		ncsi_reset_dev(&ndp->ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int ncsi_clear_interface_nl(struct sk_buff *msg, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	if (!info || !info->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	if (!info->attrs[NCSI_ATTR_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			       nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	/* Reset any whitelists and disable multi mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	ndp->package_whitelist = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	ndp->multi_package = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		spin_lock_irqsave(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		np->multi_channel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		np->channel_whitelist = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		np->preferred_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		spin_unlock_irqrestore(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	netdev_info(ndp->ndev.dev, "NCSI: Cleared preferred package/channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	/* Update channel configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	if (!(ndp->flags & NCSI_DEV_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		ncsi_reset_dev(&ndp->ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int ncsi_send_cmd_nl(struct sk_buff *msg, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	struct ncsi_pkt_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct ncsi_cmd_arg nca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	u32 package_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	u32 channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	int len, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (!info || !info->attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	if (!info->attrs[NCSI_ATTR_IFINDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	if (!info->attrs[NCSI_ATTR_PACKAGE_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	if (!info->attrs[NCSI_ATTR_CHANNEL_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if (!info->attrs[NCSI_ATTR_DATA]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			       nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	if (!ndp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	if (package_id >= NCSI_MAX_PACKAGE || channel_id >= NCSI_MAX_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		ret = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		goto out_netlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	len = nla_len(info->attrs[NCSI_ATTR_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if (len < sizeof(struct ncsi_pkt_hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		netdev_info(ndp->ndev.dev, "NCSI: no command to send %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			    package_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		goto out_netlink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		data = (unsigned char *)nla_data(info->attrs[NCSI_ATTR_DATA]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	hdr = (struct ncsi_pkt_hdr *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	nca.ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	nca.package = (unsigned char)package_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	nca.channel = (unsigned char)channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	nca.type = hdr->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	nca.req_flags = NCSI_REQ_FLAG_NETLINK_DRIVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	nca.info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	nca.payload = ntohs(hdr->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	nca.data = data + sizeof(*hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) out_netlink:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			   "NCSI: Error %d sending command\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			   ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		ncsi_send_netlink_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 				      info->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 				      info->snd_portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 				      info->nlhdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 				      ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int ncsi_send_netlink_rsp(struct ncsi_request *nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 			  struct ncsi_package *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			  struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	net = dev_net(nr->rsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	hdr = genlmsg_put(skb, nr->snd_portid, nr->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 			  &ncsi_genl_family, 0, NCSI_CMD_SEND_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	nla_put_u32(skb, NCSI_ATTR_IFINDEX, nr->rsp->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	if (np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, np->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	if (nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, NCSI_RESERVED_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	rc = nla_put(skb, NCSI_ATTR_DATA, nr->rsp->len, (void *)nr->rsp->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	return genlmsg_unicast(net, skb, nr->snd_portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int ncsi_send_netlink_timeout(struct ncsi_request *nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 			      struct ncsi_package *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 			      struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	hdr = genlmsg_put(skb, nr->snd_portid, nr->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			  &ncsi_genl_family, 0, NCSI_CMD_SEND_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	if (!hdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	net = dev_net(nr->cmd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	nla_put_u32(skb, NCSI_ATTR_IFINDEX, nr->cmd->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	if (np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, np->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 			    NCSI_PACKAGE_INDEX((((struct ncsi_pkt_hdr *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 						 nr->cmd->data)->channel)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	if (nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, NCSI_RESERVED_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	return genlmsg_unicast(net, skb, nr->snd_portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int ncsi_send_netlink_err(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 			  u32 snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 			  u32 snd_portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 			  struct nlmsghdr *nlhdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 			  int err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	struct nlmsghdr *nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	struct nlmsgerr *nle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	net = dev_net(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	nlh = nlmsg_put(skb, snd_portid, snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 			NLMSG_ERROR, sizeof(*nle), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	nle = (struct nlmsgerr *)nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	nle->error = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	memcpy(&nle->msg, nlhdr, sizeof(*nlh));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	nlmsg_end(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	return nlmsg_unicast(net->genl_sock, skb, snd_portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int ncsi_set_package_mask_nl(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 				    struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	if (!info || !info->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	if (!info->attrs[NCSI_ATTR_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	if (!info->attrs[NCSI_ATTR_PACKAGE_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			       nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	if (nla_get_flag(info->attrs[NCSI_ATTR_MULTI_FLAG])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		if (ndp->flags & NCSI_DEV_HWA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 			ndp->multi_package = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 			netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 				   "NCSI: Can't use multiple packages without HWA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 			rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		ndp->multi_package = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		ndp->package_whitelist =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 			nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_MASK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		/* Update channel configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		if (!(ndp->flags & NCSI_DEV_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 			ncsi_reset_dev(&ndp->ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int ncsi_set_channel_mask_nl(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 				    struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	struct ncsi_package *np, *package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	struct ncsi_channel *nc, *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	u32 package_id, channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	if (!info || !info->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	if (!info->attrs[NCSI_ATTR_IFINDEX])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	if (!info->attrs[NCSI_ATTR_PACKAGE_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	if (!info->attrs[NCSI_ATTR_CHANNEL_MASK])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 			       nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	package = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	NCSI_FOR_EACH_PACKAGE(ndp, np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 		if (np->id == package_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 			package = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	if (!package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	spin_lock_irqsave(&package->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	if (info->attrs[NCSI_ATTR_CHANNEL_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 		NCSI_FOR_EACH_CHANNEL(np, nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 			if (nc->id == channel_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 				channel = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 		if (!channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 			spin_unlock_irqrestore(&package->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 			return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 		netdev_dbg(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 			   "NCSI: Channel %u set as preferred channel\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 			   channel->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	package->channel_whitelist =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_MASK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	if (package->channel_whitelist == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 		netdev_dbg(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 			   "NCSI: Package %u set to all channels disabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 			   package->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	package->preferred_channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	if (nla_get_flag(info->attrs[NCSI_ATTR_MULTI_FLAG])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		package->multi_channel = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		netdev_info(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 			    "NCSI: Multi-channel enabled on package %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 			    package_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 		package->multi_channel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	spin_unlock_irqrestore(&package->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	/* Update channel configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	if (!(ndp->flags & NCSI_DEV_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 		ncsi_reset_dev(&ndp->ndev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static const struct genl_small_ops ncsi_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 		.cmd = NCSI_CMD_PKG_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 		.doit = ncsi_pkg_info_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 		.dumpit = ncsi_pkg_info_all_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		.flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 		.cmd = NCSI_CMD_SET_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 		.doit = ncsi_set_interface_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 		.cmd = NCSI_CMD_CLEAR_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 		.doit = ncsi_clear_interface_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 		.cmd = NCSI_CMD_SEND_CMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 		.doit = ncsi_send_cmd_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		.cmd = NCSI_CMD_SET_PACKAGE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 		.doit = ncsi_set_package_mask_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 		.cmd = NCSI_CMD_SET_CHANNEL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 		.doit = ncsi_set_channel_mask_nl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static struct genl_family ncsi_genl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	.name = "NCSI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	.version = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	.maxattr = NCSI_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	.policy = ncsi_genl_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	.module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	.small_ops = ncsi_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	.n_small_ops = ARRAY_SIZE(ncsi_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static int __init ncsi_init_netlink(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	return genl_register_family(&ncsi_genl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) subsys_initcall(ncsi_init_netlink);