195f510d0SVladimir Oltean // SPDX-License-Identifier: GPL-2.0 295f510d0SVladimir Oltean /* Copyright 2022 NXP 395f510d0SVladimir Oltean */ 495f510d0SVladimir Oltean #include <linux/netdevice.h> 595f510d0SVladimir Oltean #include <net/rtnetlink.h> 695f510d0SVladimir Oltean 795f510d0SVladimir Oltean #include "dsa_priv.h" 8*09f92341SVladimir Oltean #include "slave.h" 995f510d0SVladimir Oltean 1095f510d0SVladimir Oltean static const struct nla_policy dsa_policy[IFLA_DSA_MAX + 1] = { 1195f510d0SVladimir Oltean [IFLA_DSA_MASTER] = { .type = NLA_U32 }, 1295f510d0SVladimir Oltean }; 1395f510d0SVladimir Oltean 1495f510d0SVladimir Oltean static int dsa_changelink(struct net_device *dev, struct nlattr *tb[], 1595f510d0SVladimir Oltean struct nlattr *data[], 1695f510d0SVladimir Oltean struct netlink_ext_ack *extack) 1795f510d0SVladimir Oltean { 1895f510d0SVladimir Oltean int err; 1995f510d0SVladimir Oltean 2095f510d0SVladimir Oltean if (!data) 2195f510d0SVladimir Oltean return 0; 2295f510d0SVladimir Oltean 2395f510d0SVladimir Oltean if (data[IFLA_DSA_MASTER]) { 2495f510d0SVladimir Oltean u32 ifindex = nla_get_u32(data[IFLA_DSA_MASTER]); 2595f510d0SVladimir Oltean struct net_device *master; 2695f510d0SVladimir Oltean 2795f510d0SVladimir Oltean master = __dev_get_by_index(dev_net(dev), ifindex); 2895f510d0SVladimir Oltean if (!master) 2995f510d0SVladimir Oltean return -EINVAL; 3095f510d0SVladimir Oltean 3195f510d0SVladimir Oltean err = dsa_slave_change_master(dev, master, extack); 3295f510d0SVladimir Oltean if (err) 3395f510d0SVladimir Oltean return err; 3495f510d0SVladimir Oltean } 3595f510d0SVladimir Oltean 3695f510d0SVladimir Oltean return 0; 3795f510d0SVladimir Oltean } 3895f510d0SVladimir Oltean 3995f510d0SVladimir Oltean static size_t dsa_get_size(const struct net_device *dev) 4095f510d0SVladimir Oltean { 4195f510d0SVladimir Oltean return nla_total_size(sizeof(u32)) + /* IFLA_DSA_MASTER */ 4295f510d0SVladimir Oltean 0; 4395f510d0SVladimir Oltean } 4495f510d0SVladimir Oltean 4595f510d0SVladimir Oltean static int dsa_fill_info(struct sk_buff *skb, const struct net_device *dev) 4695f510d0SVladimir Oltean { 4795f510d0SVladimir Oltean struct net_device *master = dsa_slave_to_master(dev); 4895f510d0SVladimir Oltean 4995f510d0SVladimir Oltean if (nla_put_u32(skb, IFLA_DSA_MASTER, master->ifindex)) 5095f510d0SVladimir Oltean return -EMSGSIZE; 5195f510d0SVladimir Oltean 5295f510d0SVladimir Oltean return 0; 5395f510d0SVladimir Oltean } 5495f510d0SVladimir Oltean 5595f510d0SVladimir Oltean struct rtnl_link_ops dsa_link_ops __read_mostly = { 5695f510d0SVladimir Oltean .kind = "dsa", 5795f510d0SVladimir Oltean .priv_size = sizeof(struct dsa_port), 5895f510d0SVladimir Oltean .maxtype = IFLA_DSA_MAX, 5995f510d0SVladimir Oltean .policy = dsa_policy, 6095f510d0SVladimir Oltean .changelink = dsa_changelink, 6195f510d0SVladimir Oltean .get_size = dsa_get_size, 6295f510d0SVladimir Oltean .fill_info = dsa_fill_info, 6356378f3cSVladimir Oltean .netns_refund = true, 6495f510d0SVladimir Oltean }; 65