net: qualcomm: rmnet: Allow to configure flags for existing devices
authorSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Tue, 12 Dec 2017 00:30:15 +0000 (17:30 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 13 Dec 2017 19:01:09 +0000 (14:01 -0500)
Add an option to configure the mux id, aggregation and commad feature
for existing rmnet devices. Implement the changelink netlink
operation for this.

Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c

index 7a4c26e5a31d2062d27e4c730f0b702fc84ee1d6..cedacddf50fb893e72f69cc5b0990d25cca09c60 100644 (file)
@@ -320,6 +320,45 @@ static int rmnet_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
        return 0;
 }
 
+static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
+                           struct nlattr *data[],
+                           struct netlink_ext_ack *extack)
+{
+       struct rmnet_priv *priv = netdev_priv(dev);
+       struct net_device *real_dev;
+       struct rmnet_endpoint *ep;
+       struct rmnet_port *port;
+       u16 mux_id;
+
+       real_dev = __dev_get_by_index(dev_net(dev),
+                                     nla_get_u32(tb[IFLA_LINK]));
+
+       if (!real_dev || !dev || !rmnet_is_real_dev_registered(real_dev))
+               return -ENODEV;
+
+       port = rmnet_get_port_rtnl(real_dev);
+
+       if (data[IFLA_VLAN_ID]) {
+               mux_id = nla_get_u16(data[IFLA_VLAN_ID]);
+               ep = rmnet_get_endpoint(port, priv->mux_id);
+
+               hlist_del_init_rcu(&ep->hlnode);
+               hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
+
+               ep->mux_id = mux_id;
+               priv->mux_id = mux_id;
+       }
+
+       if (data[IFLA_VLAN_FLAGS]) {
+               struct ifla_vlan_flags *flags;
+
+               flags = nla_data(data[IFLA_VLAN_FLAGS]);
+               port->ingress_data_format = flags->flags & flags->mask;
+       }
+
+       return 0;
+}
+
 static size_t rmnet_get_size(const struct net_device *dev)
 {
        return nla_total_size(2) /* IFLA_VLAN_ID */ +
@@ -335,6 +374,7 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = {
        .newlink        = rmnet_newlink,
        .dellink        = rmnet_dellink,
        .get_size       = rmnet_get_size,
+       .changelink     = rmnet_changelink,
 };
 
 /* Needs either rcu_read_lock() or rtnl lock */