Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +92 −1 Original line number Diff line number Diff line Loading @@ -109,6 +109,36 @@ static int rmnet_register_real_device(struct net_device *real_dev) return 0; } static void rmnet_unregister_bridge(struct net_device *dev, struct rmnet_port *port) { struct net_device *rmnet_dev, *bridge_dev; struct rmnet_port *bridge_port; if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) return; /* bridge slave handling */ if (!port->nr_rmnet_devs) { rmnet_dev = netdev_master_upper_dev_get_rcu(dev); netdev_upper_dev_unlink(dev, rmnet_dev); bridge_dev = port->bridge_ep; bridge_port = rmnet_get_port_rtnl(bridge_dev); bridge_port->bridge_ep = NULL; bridge_port->rmnet_mode = RMNET_EPMODE_VND; } else { bridge_dev = port->bridge_ep; bridge_port = rmnet_get_port_rtnl(bridge_dev); rmnet_dev = netdev_master_upper_dev_get_rcu(bridge_dev); netdev_upper_dev_unlink(bridge_dev, rmnet_dev); rmnet_unregister_real_device(bridge_dev, bridge_port); } } static int rmnet_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) Loading Loading @@ -190,10 +220,10 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head) ep = rmnet_get_endpoint(port, mux_id); if (ep) { hlist_del_init_rcu(&ep->hlnode); rmnet_unregister_bridge(dev, port); rmnet_vnd_dellink(mux_id, port, ep); kfree(ep); } rmnet_unregister_real_device(real_dev, port); unregister_netdevice_queue(dev, head); Loading Loading @@ -237,6 +267,8 @@ static void rmnet_force_unassociate_device(struct net_device *dev) d.port = port; rcu_read_lock(); rmnet_unregister_bridge(dev, port); netdev_walk_all_lower_dev_rcu(real_dev, rmnet_dev_walk_unreg, &d); rcu_read_unlock(); unregister_netdevice_many(&list); Loading Loading @@ -321,6 +353,65 @@ struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id) return NULL; } int rmnet_add_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev, struct netlink_ext_ack *extack) { struct rmnet_priv *priv = netdev_priv(rmnet_dev); struct net_device *real_dev = priv->real_dev; struct rmnet_port *port, *slave_port; int err; port = rmnet_get_port(real_dev); /* If there is more than one rmnet dev attached, its probably being * used for muxing. Skip the briding in that case */ if (port->nr_rmnet_devs > 1) return -EINVAL; if (rmnet_is_real_dev_registered(slave_dev)) return -EBUSY; err = rmnet_register_real_device(slave_dev); if (err) return -EBUSY; err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL, extack); if (err) return -EINVAL; slave_port = rmnet_get_port(slave_dev); slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; slave_port->bridge_ep = real_dev; port->rmnet_mode = RMNET_EPMODE_BRIDGE; port->bridge_ep = slave_dev; netdev_dbg(slave_dev, "registered with rmnet as slave\n"); return 0; } int rmnet_del_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev) { struct rmnet_priv *priv = netdev_priv(rmnet_dev); struct net_device *real_dev = priv->real_dev; struct rmnet_port *port, *slave_port; port = rmnet_get_port(real_dev); port->rmnet_mode = RMNET_EPMODE_VND; port->bridge_ep = NULL; netdev_upper_dev_unlink(slave_dev, rmnet_dev); slave_port = rmnet_get_port(slave_dev); rmnet_unregister_real_device(slave_dev, slave_port); netdev_dbg(slave_dev, "removed from rmnet as slave\n"); return 0; } /* Startup/Shutdown */ static int __init rmnet_init(void) Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +6 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct rmnet_port { u8 nr_rmnet_devs; u8 rmnet_mode; struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; struct net_device *bridge_ep; }; extern struct rtnl_link_ops rmnet_link_ops; Loading @@ -47,5 +48,9 @@ struct rmnet_priv { struct rmnet_port *rmnet_get_port(struct net_device *real_dev); struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); int rmnet_add_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev, struct netlink_ext_ack *extack); int rmnet_del_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev); #endif /* _RMNET_CONFIG_H_ */ drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c +22 −4 Original line number Diff line number Diff line Loading @@ -149,6 +149,17 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, return RMNET_MAP_SUCCESS; } static rx_handler_result_t rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev) { if (bridge_dev) { skb->dev = bridge_dev; dev_queue_xmit(skb); } return RX_HANDLER_CONSUMED; } /* Ingress / Egress Entry Points */ /* Processes packet as per ingress data format for receiving device. Logical Loading @@ -157,10 +168,10 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, */ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) { struct rmnet_port *port; int rc = RX_HANDLER_CONSUMED; struct sk_buff *skb = *pskb; struct rmnet_port *port; struct net_device *dev; int rc; if (!skb) return RX_HANDLER_CONSUMED; Loading @@ -168,8 +179,15 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) dev = skb->dev; port = rmnet_get_port(dev); switch (port->rmnet_mode) { case RMNET_EPMODE_VND: if (port->ingress_data_format & RMNET_INGRESS_FORMAT_MAP) rc = rmnet_map_ingress_handler(skb, port); break; case RMNET_EPMODE_BRIDGE: rc = rmnet_bridge_handler(skb, port->bridge_ep); break; } return rc; } Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +2 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ static const struct net_device_ops rmnet_vnd_ops = { .ndo_start_xmit = rmnet_vnd_start_xmit, .ndo_change_mtu = rmnet_vnd_change_mtu, .ndo_get_iflink = rmnet_vnd_get_iflink, .ndo_add_slave = rmnet_add_bridge, .ndo_del_slave = rmnet_del_bridge, }; /* Called by kernel whenever a new rmnet<n> device is created. Sets MTU, Loading Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +92 −1 Original line number Diff line number Diff line Loading @@ -109,6 +109,36 @@ static int rmnet_register_real_device(struct net_device *real_dev) return 0; } static void rmnet_unregister_bridge(struct net_device *dev, struct rmnet_port *port) { struct net_device *rmnet_dev, *bridge_dev; struct rmnet_port *bridge_port; if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) return; /* bridge slave handling */ if (!port->nr_rmnet_devs) { rmnet_dev = netdev_master_upper_dev_get_rcu(dev); netdev_upper_dev_unlink(dev, rmnet_dev); bridge_dev = port->bridge_ep; bridge_port = rmnet_get_port_rtnl(bridge_dev); bridge_port->bridge_ep = NULL; bridge_port->rmnet_mode = RMNET_EPMODE_VND; } else { bridge_dev = port->bridge_ep; bridge_port = rmnet_get_port_rtnl(bridge_dev); rmnet_dev = netdev_master_upper_dev_get_rcu(bridge_dev); netdev_upper_dev_unlink(bridge_dev, rmnet_dev); rmnet_unregister_real_device(bridge_dev, bridge_port); } } static int rmnet_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) Loading Loading @@ -190,10 +220,10 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head) ep = rmnet_get_endpoint(port, mux_id); if (ep) { hlist_del_init_rcu(&ep->hlnode); rmnet_unregister_bridge(dev, port); rmnet_vnd_dellink(mux_id, port, ep); kfree(ep); } rmnet_unregister_real_device(real_dev, port); unregister_netdevice_queue(dev, head); Loading Loading @@ -237,6 +267,8 @@ static void rmnet_force_unassociate_device(struct net_device *dev) d.port = port; rcu_read_lock(); rmnet_unregister_bridge(dev, port); netdev_walk_all_lower_dev_rcu(real_dev, rmnet_dev_walk_unreg, &d); rcu_read_unlock(); unregister_netdevice_many(&list); Loading Loading @@ -321,6 +353,65 @@ struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id) return NULL; } int rmnet_add_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev, struct netlink_ext_ack *extack) { struct rmnet_priv *priv = netdev_priv(rmnet_dev); struct net_device *real_dev = priv->real_dev; struct rmnet_port *port, *slave_port; int err; port = rmnet_get_port(real_dev); /* If there is more than one rmnet dev attached, its probably being * used for muxing. Skip the briding in that case */ if (port->nr_rmnet_devs > 1) return -EINVAL; if (rmnet_is_real_dev_registered(slave_dev)) return -EBUSY; err = rmnet_register_real_device(slave_dev); if (err) return -EBUSY; err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL, extack); if (err) return -EINVAL; slave_port = rmnet_get_port(slave_dev); slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; slave_port->bridge_ep = real_dev; port->rmnet_mode = RMNET_EPMODE_BRIDGE; port->bridge_ep = slave_dev; netdev_dbg(slave_dev, "registered with rmnet as slave\n"); return 0; } int rmnet_del_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev) { struct rmnet_priv *priv = netdev_priv(rmnet_dev); struct net_device *real_dev = priv->real_dev; struct rmnet_port *port, *slave_port; port = rmnet_get_port(real_dev); port->rmnet_mode = RMNET_EPMODE_VND; port->bridge_ep = NULL; netdev_upper_dev_unlink(slave_dev, rmnet_dev); slave_port = rmnet_get_port(slave_dev); rmnet_unregister_real_device(slave_dev, slave_port); netdev_dbg(slave_dev, "removed from rmnet as slave\n"); return 0; } /* Startup/Shutdown */ static int __init rmnet_init(void) Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +6 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct rmnet_port { u8 nr_rmnet_devs; u8 rmnet_mode; struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; struct net_device *bridge_ep; }; extern struct rtnl_link_ops rmnet_link_ops; Loading @@ -47,5 +48,9 @@ struct rmnet_priv { struct rmnet_port *rmnet_get_port(struct net_device *real_dev); struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); int rmnet_add_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev, struct netlink_ext_ack *extack); int rmnet_del_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev); #endif /* _RMNET_CONFIG_H_ */
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c +22 −4 Original line number Diff line number Diff line Loading @@ -149,6 +149,17 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, return RMNET_MAP_SUCCESS; } static rx_handler_result_t rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev) { if (bridge_dev) { skb->dev = bridge_dev; dev_queue_xmit(skb); } return RX_HANDLER_CONSUMED; } /* Ingress / Egress Entry Points */ /* Processes packet as per ingress data format for receiving device. Logical Loading @@ -157,10 +168,10 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, */ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) { struct rmnet_port *port; int rc = RX_HANDLER_CONSUMED; struct sk_buff *skb = *pskb; struct rmnet_port *port; struct net_device *dev; int rc; if (!skb) return RX_HANDLER_CONSUMED; Loading @@ -168,8 +179,15 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) dev = skb->dev; port = rmnet_get_port(dev); switch (port->rmnet_mode) { case RMNET_EPMODE_VND: if (port->ingress_data_format & RMNET_INGRESS_FORMAT_MAP) rc = rmnet_map_ingress_handler(skb, port); break; case RMNET_EPMODE_BRIDGE: rc = rmnet_bridge_handler(skb, port->bridge_ep); break; } return rc; } Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +2 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ static const struct net_device_ops rmnet_vnd_ops = { .ndo_start_xmit = rmnet_vnd_start_xmit, .ndo_change_mtu = rmnet_vnd_change_mtu, .ndo_get_iflink = rmnet_vnd_get_iflink, .ndo_add_slave = rmnet_add_bridge, .ndo_del_slave = rmnet_del_bridge, }; /* Called by kernel whenever a new rmnet<n> device is created. Sets MTU, Loading