Commit 22d37b6b authored by David S. Miller's avatar David S. Miller

Merge branch 'geneve-vxlan-deps'

Hannes Frederic Sowa says:

====================
net: network drivers should not depend on geneve/vxlan

This patchset removes the dependency of network drivers on vxlan or
geneve, so those don't get autoloaded when the nic driver is loaded.

Also audited the code such that vxlan_get_rx_port and geneve_get_rx_port
are not called without rtnl lock.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7f348a60 681e683f
...@@ -4890,11 +4890,13 @@ static int be_resume(struct be_adapter *adapter) ...@@ -4890,11 +4890,13 @@ static int be_resume(struct be_adapter *adapter)
if (status) if (status)
return status; return status;
if (netif_running(netdev)) { rtnl_lock();
if (netif_running(netdev))
status = be_open(netdev); status = be_open(netdev);
rtnl_unlock();
if (status) if (status)
return status; return status;
}
netif_device_attach(netdev); netif_device_attach(netdev);
......
...@@ -2287,8 +2287,10 @@ static void fm10k_io_resume(struct pci_dev *pdev) ...@@ -2287,8 +2287,10 @@ static void fm10k_io_resume(struct pci_dev *pdev)
/* reassociate interrupts */ /* reassociate interrupts */
fm10k_mbx_request_irq(interface); fm10k_mbx_request_irq(interface);
rtnl_lock();
if (netif_running(netdev)) if (netif_running(netdev))
err = fm10k_open(netdev); err = fm10k_open(netdev);
rtnl_unlock();
/* final check of hardware state before registering the interface */ /* final check of hardware state before registering the interface */
err = err ? : fm10k_hw_ready(interface); err = err ? : fm10k_hw_ready(interface);
......
...@@ -7192,10 +7192,12 @@ static void ixgbe_service_task(struct work_struct *work) ...@@ -7192,10 +7192,12 @@ static void ixgbe_service_task(struct work_struct *work)
return; return;
} }
#ifdef CONFIG_IXGBE_VXLAN #ifdef CONFIG_IXGBE_VXLAN
rtnl_lock();
if (adapter->flags2 & IXGBE_FLAG2_VXLAN_REREG_NEEDED) { if (adapter->flags2 & IXGBE_FLAG2_VXLAN_REREG_NEEDED) {
adapter->flags2 &= ~IXGBE_FLAG2_VXLAN_REREG_NEEDED; adapter->flags2 &= ~IXGBE_FLAG2_VXLAN_REREG_NEEDED;
vxlan_get_rx_port(adapter->netdev); vxlan_get_rx_port(adapter->netdev);
} }
rtnl_unlock();
#endif /* CONFIG_IXGBE_VXLAN */ #endif /* CONFIG_IXGBE_VXLAN */
ixgbe_reset_subtask(adapter); ixgbe_reset_subtask(adapter);
ixgbe_phy_interrupt_subtask(adapter); ixgbe_phy_interrupt_subtask(adapter);
......
...@@ -1856,6 +1856,7 @@ static void mlx4_en_restart(struct work_struct *work) ...@@ -1856,6 +1856,7 @@ static void mlx4_en_restart(struct work_struct *work)
en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port); en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
rtnl_lock();
mutex_lock(&mdev->state_lock); mutex_lock(&mdev->state_lock);
if (priv->port_up) { if (priv->port_up) {
mlx4_en_stop_port(dev, 1); mlx4_en_stop_port(dev, 1);
...@@ -1863,6 +1864,7 @@ static void mlx4_en_restart(struct work_struct *work) ...@@ -1863,6 +1864,7 @@ static void mlx4_en_restart(struct work_struct *work)
en_err(priv, "Failed restarting port %d\n", priv->port); en_err(priv, "Failed restarting port %d\n", priv->port);
} }
mutex_unlock(&mdev->state_lock); mutex_unlock(&mdev->state_lock);
rtnl_unlock();
} }
static void mlx4_en_clear_stats(struct net_device *dev) static void mlx4_en_clear_stats(struct net_device *dev)
......
...@@ -3952,8 +3952,14 @@ static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev, ...@@ -3952,8 +3952,14 @@ static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev,
static pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev) static pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev)
{ {
return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : pci_ers_result_t res;
rtnl_lock();
res = qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
PCI_ERS_RESULT_RECOVERED; PCI_ERS_RESULT_RECOVERED;
rtnl_unlock();
return res;
} }
static void qlcnic_82xx_io_resume(struct pci_dev *pdev) static void qlcnic_82xx_io_resume(struct pci_dev *pdev)
......
...@@ -1172,7 +1172,7 @@ static struct device_type geneve_type = { ...@@ -1172,7 +1172,7 @@ static struct device_type geneve_type = {
* supply the listening GENEVE udp ports. Callers are expected * supply the listening GENEVE udp ports. Callers are expected
* to implement the ndo_add_geneve_port. * to implement the ndo_add_geneve_port.
*/ */
void geneve_get_rx_port(struct net_device *dev) static void geneve_push_rx_ports(struct net_device *dev)
{ {
struct net *net = dev_net(dev); struct net *net = dev_net(dev);
struct geneve_net *gn = net_generic(net, geneve_net_id); struct geneve_net *gn = net_generic(net, geneve_net_id);
...@@ -1181,6 +1181,9 @@ void geneve_get_rx_port(struct net_device *dev) ...@@ -1181,6 +1181,9 @@ void geneve_get_rx_port(struct net_device *dev)
struct sock *sk; struct sock *sk;
__be16 port; __be16 port;
if (!dev->netdev_ops->ndo_add_geneve_port)
return;
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(gs, &gn->sock_list, list) { list_for_each_entry_rcu(gs, &gn->sock_list, list) {
sk = gs->sock->sk; sk = gs->sock->sk;
...@@ -1190,7 +1193,6 @@ void geneve_get_rx_port(struct net_device *dev) ...@@ -1190,7 +1193,6 @@ void geneve_get_rx_port(struct net_device *dev)
} }
rcu_read_unlock(); rcu_read_unlock();
} }
EXPORT_SYMBOL_GPL(geneve_get_rx_port);
/* Initialize the device structure. */ /* Initialize the device structure. */
static void geneve_setup(struct net_device *dev) static void geneve_setup(struct net_device *dev)
...@@ -1538,6 +1540,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, ...@@ -1538,6 +1540,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
} }
EXPORT_SYMBOL_GPL(geneve_dev_create_fb); EXPORT_SYMBOL_GPL(geneve_dev_create_fb);
static int geneve_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
if (event == NETDEV_OFFLOAD_PUSH_GENEVE)
geneve_push_rx_ports(dev);
return NOTIFY_DONE;
}
static struct notifier_block geneve_notifier_block __read_mostly = {
.notifier_call = geneve_netdevice_event,
};
static __net_init int geneve_init_net(struct net *net) static __net_init int geneve_init_net(struct net *net)
{ {
struct geneve_net *gn = net_generic(net, geneve_net_id); struct geneve_net *gn = net_generic(net, geneve_net_id);
...@@ -1590,11 +1607,18 @@ static int __init geneve_init_module(void) ...@@ -1590,11 +1607,18 @@ static int __init geneve_init_module(void)
if (rc) if (rc)
goto out1; goto out1;
rc = rtnl_link_register(&geneve_link_ops); rc = register_netdevice_notifier(&geneve_notifier_block);
if (rc) if (rc)
goto out2; goto out2;
rc = rtnl_link_register(&geneve_link_ops);
if (rc)
goto out3;
return 0; return 0;
out3:
unregister_netdevice_notifier(&geneve_notifier_block);
out2: out2:
unregister_pernet_subsys(&geneve_net_ops); unregister_pernet_subsys(&geneve_net_ops);
out1: out1:
...@@ -1605,6 +1629,7 @@ late_initcall(geneve_init_module); ...@@ -1605,6 +1629,7 @@ late_initcall(geneve_init_module);
static void __exit geneve_cleanup_module(void) static void __exit geneve_cleanup_module(void)
{ {
rtnl_link_unregister(&geneve_link_ops); rtnl_link_unregister(&geneve_link_ops);
unregister_netdevice_notifier(&geneve_notifier_block);
unregister_pernet_subsys(&geneve_net_ops); unregister_pernet_subsys(&geneve_net_ops);
} }
module_exit(geneve_cleanup_module); module_exit(geneve_cleanup_module);
......
...@@ -2527,7 +2527,7 @@ static struct device_type vxlan_type = { ...@@ -2527,7 +2527,7 @@ static struct device_type vxlan_type = {
* supply the listening VXLAN udp ports. Callers are expected * supply the listening VXLAN udp ports. Callers are expected
* to implement the ndo_add_vxlan_port. * to implement the ndo_add_vxlan_port.
*/ */
void vxlan_get_rx_port(struct net_device *dev) static void vxlan_push_rx_ports(struct net_device *dev)
{ {
struct vxlan_sock *vs; struct vxlan_sock *vs;
struct net *net = dev_net(dev); struct net *net = dev_net(dev);
...@@ -2536,6 +2536,9 @@ void vxlan_get_rx_port(struct net_device *dev) ...@@ -2536,6 +2536,9 @@ void vxlan_get_rx_port(struct net_device *dev)
__be16 port; __be16 port;
unsigned int i; unsigned int i;
if (!dev->netdev_ops->ndo_add_vxlan_port)
return;
spin_lock(&vn->sock_lock); spin_lock(&vn->sock_lock);
for (i = 0; i < PORT_HASH_SIZE; ++i) { for (i = 0; i < PORT_HASH_SIZE; ++i) {
hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) { hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) {
...@@ -2547,7 +2550,6 @@ void vxlan_get_rx_port(struct net_device *dev) ...@@ -2547,7 +2550,6 @@ void vxlan_get_rx_port(struct net_device *dev)
} }
spin_unlock(&vn->sock_lock); spin_unlock(&vn->sock_lock);
} }
EXPORT_SYMBOL_GPL(vxlan_get_rx_port);
/* Initialize the device structure. */ /* Initialize the device structure. */
static void vxlan_setup(struct net_device *dev) static void vxlan_setup(struct net_device *dev)
...@@ -3283,7 +3285,7 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn, ...@@ -3283,7 +3285,7 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
unregister_netdevice_many(&list_kill); unregister_netdevice_many(&list_kill);
} }
static int vxlan_lowerdev_event(struct notifier_block *unused, static int vxlan_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_device *dev = netdev_notifier_info_to_dev(ptr);
...@@ -3291,12 +3293,14 @@ static int vxlan_lowerdev_event(struct notifier_block *unused, ...@@ -3291,12 +3293,14 @@ static int vxlan_lowerdev_event(struct notifier_block *unused,
if (event == NETDEV_UNREGISTER) if (event == NETDEV_UNREGISTER)
vxlan_handle_lowerdev_unregister(vn, dev); vxlan_handle_lowerdev_unregister(vn, dev);
else if (event == NETDEV_OFFLOAD_PUSH_VXLAN)
vxlan_push_rx_ports(dev);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block vxlan_notifier_block __read_mostly = { static struct notifier_block vxlan_notifier_block __read_mostly = {
.notifier_call = vxlan_lowerdev_event, .notifier_call = vxlan_netdevice_event,
}; };
static __net_init int vxlan_init_net(struct net *net) static __net_init int vxlan_init_net(struct net *net)
......
...@@ -2244,6 +2244,8 @@ struct netdev_lag_lower_state_info { ...@@ -2244,6 +2244,8 @@ struct netdev_lag_lower_state_info {
#define NETDEV_BONDING_INFO 0x0019 #define NETDEV_BONDING_INFO 0x0019
#define NETDEV_PRECHANGEUPPER 0x001A #define NETDEV_PRECHANGEUPPER 0x001A
#define NETDEV_CHANGELOWERSTATE 0x001B #define NETDEV_CHANGELOWERSTATE 0x001B
#define NETDEV_OFFLOAD_PUSH_VXLAN 0x001C
#define NETDEV_OFFLOAD_PUSH_GENEVE 0x001D
int register_netdevice_notifier(struct notifier_block *nb); int register_netdevice_notifier(struct notifier_block *nb);
int unregister_netdevice_notifier(struct notifier_block *nb); int unregister_netdevice_notifier(struct notifier_block *nb);
......
...@@ -62,13 +62,11 @@ struct genevehdr { ...@@ -62,13 +62,11 @@ struct genevehdr {
struct geneve_opt options[]; struct geneve_opt options[];
}; };
#if IS_ENABLED(CONFIG_GENEVE)
void geneve_get_rx_port(struct net_device *netdev);
#else
static inline void geneve_get_rx_port(struct net_device *netdev) static inline void geneve_get_rx_port(struct net_device *netdev)
{ {
ASSERT_RTNL();
call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_GENEVE, netdev);
} }
#endif
#ifdef CONFIG_INET #ifdef CONFIG_INET
struct net_device *geneve_dev_create_fb(struct net *net, const char *name, struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
......
...@@ -390,13 +390,11 @@ static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset) ...@@ -390,13 +390,11 @@ static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset)
return vni_field; return vni_field;
} }
#if IS_ENABLED(CONFIG_VXLAN)
void vxlan_get_rx_port(struct net_device *netdev);
#else
static inline void vxlan_get_rx_port(struct net_device *netdev) static inline void vxlan_get_rx_port(struct net_device *netdev)
{ {
ASSERT_RTNL();
call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_VXLAN, netdev);
} }
#endif
static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs) static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)
{ {
......
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