|
@@ -43,12 +43,6 @@
|
|
|
|
|
|
/* Local Definitions and Declarations */
|
|
|
|
|
|
-struct rmnet_walk_data {
|
|
|
- struct net_device *real_dev;
|
|
|
- struct list_head *head;
|
|
|
- struct rmnet_port *port;
|
|
|
-};
|
|
|
-
|
|
|
static int rmnet_is_real_dev_registered(const struct net_device *real_dev)
|
|
|
{
|
|
|
return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler;
|
|
@@ -112,17 +106,14 @@ static int rmnet_register_real_device(struct net_device *real_dev)
|
|
|
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;
|
|
|
+ struct net_device *bridge_dev;
|
|
|
|
|
|
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);
|
|
@@ -132,9 +123,6 @@ static void rmnet_unregister_bridge(struct net_device *dev,
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
@@ -173,10 +161,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
|
|
|
if (err)
|
|
|
goto err1;
|
|
|
|
|
|
- err = netdev_master_upper_dev_link(dev, real_dev, NULL, NULL, extack);
|
|
|
- if (err)
|
|
|
- goto err2;
|
|
|
-
|
|
|
port->rmnet_mode = mode;
|
|
|
|
|
|
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
|
|
@@ -193,8 +177,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-err2:
|
|
|
- rmnet_vnd_dellink(mux_id, port, ep);
|
|
|
err1:
|
|
|
rmnet_unregister_real_device(real_dev, port);
|
|
|
err0:
|
|
@@ -204,14 +186,13 @@ err0:
|
|
|
|
|
|
static void rmnet_dellink(struct net_device *dev, struct list_head *head)
|
|
|
{
|
|
|
+ struct rmnet_priv *priv = netdev_priv(dev);
|
|
|
struct net_device *real_dev;
|
|
|
struct rmnet_endpoint *ep;
|
|
|
struct rmnet_port *port;
|
|
|
u8 mux_id;
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
- real_dev = netdev_master_upper_dev_get_rcu(dev);
|
|
|
- rcu_read_unlock();
|
|
|
+ real_dev = priv->real_dev;
|
|
|
|
|
|
if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
|
|
|
return;
|
|
@@ -219,7 +200,6 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
|
|
|
port = rmnet_get_port_rtnl(real_dev);
|
|
|
|
|
|
mux_id = rmnet_vnd_get_mux(dev);
|
|
|
- netdev_upper_dev_unlink(dev, real_dev);
|
|
|
|
|
|
ep = rmnet_get_endpoint(port, mux_id);
|
|
|
if (ep) {
|
|
@@ -233,30 +213,13 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
|
|
|
unregister_netdevice_queue(dev, head);
|
|
|
}
|
|
|
|
|
|
-static int rmnet_dev_walk_unreg(struct net_device *rmnet_dev, void *data)
|
|
|
-{
|
|
|
- struct rmnet_walk_data *d = data;
|
|
|
- struct rmnet_endpoint *ep;
|
|
|
- u8 mux_id;
|
|
|
-
|
|
|
- mux_id = rmnet_vnd_get_mux(rmnet_dev);
|
|
|
- ep = rmnet_get_endpoint(d->port, mux_id);
|
|
|
- if (ep) {
|
|
|
- hlist_del_init_rcu(&ep->hlnode);
|
|
|
- rmnet_vnd_dellink(mux_id, d->port, ep);
|
|
|
- kfree(ep);
|
|
|
- }
|
|
|
- netdev_upper_dev_unlink(rmnet_dev, d->real_dev);
|
|
|
- unregister_netdevice_queue(rmnet_dev, d->head);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static void rmnet_force_unassociate_device(struct net_device *dev)
|
|
|
{
|
|
|
struct net_device *real_dev = dev;
|
|
|
- struct rmnet_walk_data d;
|
|
|
+ struct hlist_node *tmp_ep;
|
|
|
+ struct rmnet_endpoint *ep;
|
|
|
struct rmnet_port *port;
|
|
|
+ unsigned long bkt_ep;
|
|
|
LIST_HEAD(list);
|
|
|
|
|
|
if (!rmnet_is_real_dev_registered(real_dev))
|
|
@@ -264,16 +227,19 @@ static void rmnet_force_unassociate_device(struct net_device *dev)
|
|
|
|
|
|
ASSERT_RTNL();
|
|
|
|
|
|
- d.real_dev = real_dev;
|
|
|
- d.head = &list;
|
|
|
-
|
|
|
port = rmnet_get_port_rtnl(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);
|
|
|
+ hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
|
|
|
+ unregister_netdevice_queue(ep->egress_dev, &list);
|
|
|
+ rmnet_vnd_dellink(ep->mux_id, port, ep);
|
|
|
+
|
|
|
+ hlist_del_init_rcu(&ep->hlnode);
|
|
|
+ kfree(ep);
|
|
|
+ }
|
|
|
+
|
|
|
rcu_read_unlock();
|
|
|
unregister_netdevice_many(&list);
|
|
|
|
|
@@ -422,11 +388,6 @@ int rmnet_add_bridge(struct net_device *rmnet_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;
|
|
@@ -449,7 +410,6 @@ int rmnet_del_bridge(struct net_device *rmnet_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);
|
|
|
|