Commit cae69256 authored by David S. Miller's avatar David S. Miller

Merge branch 'qualcomm-rmnet-Fix-issues-with-CONFIG_DEBUG_PREEMPT-enabled'

Subash Abhinov Kasiviswanathan says:

====================
net: qualcomm: rmnet: Fix issues with CONFIG_DEBUG_PREEMPT enabled

Patch 1 and 2 fixes issues identified when CONFIG_DEBUG_PREEMPT was
enabled. These involve APIs which were called in invalid contexts.

Patch 3 is a null derefence fix identified by code inspection.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9ab2323c f57bbaae
...@@ -43,12 +43,6 @@ ...@@ -43,12 +43,6 @@
/* Local Definitions and Declarations */ /* 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) static int rmnet_is_real_dev_registered(const struct net_device *real_dev)
{ {
return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler; 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) ...@@ -112,17 +106,14 @@ static int rmnet_register_real_device(struct net_device *real_dev)
static void rmnet_unregister_bridge(struct net_device *dev, static void rmnet_unregister_bridge(struct net_device *dev,
struct rmnet_port *port) struct rmnet_port *port)
{ {
struct net_device *rmnet_dev, *bridge_dev;
struct rmnet_port *bridge_port; struct rmnet_port *bridge_port;
struct net_device *bridge_dev;
if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
return; return;
/* bridge slave handling */ /* bridge slave handling */
if (!port->nr_rmnet_devs) { 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_dev = port->bridge_ep;
bridge_port = rmnet_get_port_rtnl(bridge_dev); bridge_port = rmnet_get_port_rtnl(bridge_dev);
...@@ -132,9 +123,6 @@ static void rmnet_unregister_bridge(struct net_device *dev, ...@@ -132,9 +123,6 @@ static void rmnet_unregister_bridge(struct net_device *dev,
bridge_dev = port->bridge_ep; bridge_dev = port->bridge_ep;
bridge_port = rmnet_get_port_rtnl(bridge_dev); 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); rmnet_unregister_real_device(bridge_dev, bridge_port);
} }
} }
...@@ -173,10 +161,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, ...@@ -173,10 +161,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
if (err) if (err)
goto err1; goto err1;
err = netdev_master_upper_dev_link(dev, real_dev, NULL, NULL, extack);
if (err)
goto err2;
port->rmnet_mode = mode; port->rmnet_mode = mode;
hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]); 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, ...@@ -193,8 +177,6 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
return 0; return 0;
err2:
rmnet_vnd_dellink(mux_id, port, ep);
err1: err1:
rmnet_unregister_real_device(real_dev, port); rmnet_unregister_real_device(real_dev, port);
err0: err0:
...@@ -204,14 +186,13 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, ...@@ -204,14 +186,13 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
static void rmnet_dellink(struct net_device *dev, struct list_head *head) 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 net_device *real_dev;
struct rmnet_endpoint *ep; struct rmnet_endpoint *ep;
struct rmnet_port *port; struct rmnet_port *port;
u8 mux_id; u8 mux_id;
rcu_read_lock(); real_dev = priv->real_dev;
real_dev = netdev_master_upper_dev_get_rcu(dev);
rcu_read_unlock();
if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
return; return;
...@@ -219,7 +200,6 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head) ...@@ -219,7 +200,6 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
port = rmnet_get_port_rtnl(real_dev); port = rmnet_get_port_rtnl(real_dev);
mux_id = rmnet_vnd_get_mux(dev); mux_id = rmnet_vnd_get_mux(dev);
netdev_upper_dev_unlink(dev, real_dev);
ep = rmnet_get_endpoint(port, mux_id); ep = rmnet_get_endpoint(port, mux_id);
if (ep) { if (ep) {
...@@ -233,30 +213,13 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head) ...@@ -233,30 +213,13 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head)
unregister_netdevice_queue(dev, 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) static void rmnet_force_unassociate_device(struct net_device *dev)
{ {
struct net_device *real_dev = 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; struct rmnet_port *port;
unsigned long bkt_ep;
LIST_HEAD(list); LIST_HEAD(list);
if (!rmnet_is_real_dev_registered(real_dev)) if (!rmnet_is_real_dev_registered(real_dev))
...@@ -264,16 +227,19 @@ static void rmnet_force_unassociate_device(struct net_device *dev) ...@@ -264,16 +227,19 @@ static void rmnet_force_unassociate_device(struct net_device *dev)
ASSERT_RTNL(); ASSERT_RTNL();
d.real_dev = real_dev;
d.head = &list;
port = rmnet_get_port_rtnl(dev); port = rmnet_get_port_rtnl(dev);
d.port = port;
rcu_read_lock(); rcu_read_lock();
rmnet_unregister_bridge(dev, port); 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(); rcu_read_unlock();
unregister_netdevice_many(&list); unregister_netdevice_many(&list);
...@@ -422,11 +388,6 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, ...@@ -422,11 +388,6 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
if (err) if (err)
return -EBUSY; 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_get_port(slave_dev);
slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
slave_port->bridge_ep = real_dev; slave_port->bridge_ep = real_dev;
...@@ -449,7 +410,6 @@ int rmnet_del_bridge(struct net_device *rmnet_dev, ...@@ -449,7 +410,6 @@ int rmnet_del_bridge(struct net_device *rmnet_dev,
port->rmnet_mode = RMNET_EPMODE_VND; port->rmnet_mode = RMNET_EPMODE_VND;
port->bridge_ep = NULL; port->bridge_ep = NULL;
netdev_upper_dev_unlink(slave_dev, rmnet_dev);
slave_port = rmnet_get_port(slave_dev); slave_port = rmnet_get_port(slave_dev);
rmnet_unregister_real_device(slave_dev, slave_port); rmnet_unregister_real_device(slave_dev, slave_port);
......
...@@ -38,6 +38,11 @@ static u8 rmnet_map_do_flow_control(struct sk_buff *skb, ...@@ -38,6 +38,11 @@ static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
} }
ep = rmnet_get_endpoint(port, mux_id); ep = rmnet_get_endpoint(port, mux_id);
if (!ep) {
kfree_skb(skb);
return RX_HANDLER_CONSUMED;
}
vnd = ep->egress_dev; vnd = ep->egress_dev;
ip_family = cmd->flow_control.ip_family; ip_family = cmd->flow_control.ip_family;
......
...@@ -121,7 +121,7 @@ static void rmnet_get_stats64(struct net_device *dev, ...@@ -121,7 +121,7 @@ static void rmnet_get_stats64(struct net_device *dev,
memset(&total_stats, 0, sizeof(struct rmnet_vnd_stats)); memset(&total_stats, 0, sizeof(struct rmnet_vnd_stats));
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
pcpu_ptr = this_cpu_ptr(priv->pcpu_stats); pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu);
do { do {
start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp); start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment