Commit 023cae85 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'locked-version-of-netdev_notify_peers'

Lijun Pan says:

====================
add a locked version of netdev_notify_peers

This series introduce the lockless version of netdev_notify_peers
and then apply it to the relevant drivers.

In v1, a more appropriate name __netdev_notify_peers is used;
netdev_notify_peers is converted to call the new helper.
In v2, patch 3 calls the new helper where notify variable used
to be set true.
====================

Link: https://lore.kernel.org/r/20201214211930.80778-1-ljp@linux.ibm.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 322e53d1 935d8a0a
...@@ -2171,10 +2171,8 @@ static int do_reset(struct ibmvnic_adapter *adapter, ...@@ -2171,10 +2171,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
napi_schedule(&adapter->napi[i]); napi_schedule(&adapter->napi[i]);
if (adapter->reset_reason == VNIC_RESET_FAILOVER || if (adapter->reset_reason == VNIC_RESET_FAILOVER ||
adapter->reset_reason == VNIC_RESET_MOBILITY) { adapter->reset_reason == VNIC_RESET_MOBILITY)
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); __netdev_notify_peers(netdev);
call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
}
rc = 0; rc = 0;
...@@ -2249,8 +2247,7 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter, ...@@ -2249,8 +2247,7 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
goto out; goto out;
} }
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); __netdev_notify_peers(netdev);
call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
out: out:
/* restore adapter state if reset failed */ /* restore adapter state if reset failed */
if (rc) if (rc)
......
...@@ -2050,11 +2050,11 @@ static void netvsc_link_change(struct work_struct *w) ...@@ -2050,11 +2050,11 @@ static void netvsc_link_change(struct work_struct *w)
container_of(w, struct net_device_context, dwork.work); container_of(w, struct net_device_context, dwork.work);
struct hv_device *device_obj = ndev_ctx->device_ctx; struct hv_device *device_obj = ndev_ctx->device_ctx;
struct net_device *net = hv_get_drvdata(device_obj); struct net_device *net = hv_get_drvdata(device_obj);
unsigned long flags, next_reconfig, delay;
struct netvsc_reconfig *event = NULL;
struct netvsc_device *net_device; struct netvsc_device *net_device;
struct rndis_device *rdev; struct rndis_device *rdev;
struct netvsc_reconfig *event = NULL; bool reschedule = false;
bool notify = false, reschedule = false;
unsigned long flags, next_reconfig, delay;
/* if changes are happening, comeback later */ /* if changes are happening, comeback later */
if (!rtnl_trylock()) { if (!rtnl_trylock()) {
...@@ -2103,7 +2103,7 @@ static void netvsc_link_change(struct work_struct *w) ...@@ -2103,7 +2103,7 @@ static void netvsc_link_change(struct work_struct *w)
netif_carrier_on(net); netif_carrier_on(net);
netvsc_tx_enable(net_device, net); netvsc_tx_enable(net_device, net);
} else { } else {
notify = true; __netdev_notify_peers(net);
} }
kfree(event); kfree(event);
break; break;
...@@ -2132,9 +2132,6 @@ static void netvsc_link_change(struct work_struct *w) ...@@ -2132,9 +2132,6 @@ static void netvsc_link_change(struct work_struct *w)
rtnl_unlock(); rtnl_unlock();
if (notify)
netdev_notify_peers(net);
/* link_watch only sends one notification with current state per /* link_watch only sends one notification with current state per
* second, handle next reconfig event in 2 seconds. * second, handle next reconfig event in 2 seconds.
*/ */
......
...@@ -4547,6 +4547,7 @@ void __dev_set_rx_mode(struct net_device *dev); ...@@ -4547,6 +4547,7 @@ void __dev_set_rx_mode(struct net_device *dev);
int dev_set_promiscuity(struct net_device *dev, int inc); int dev_set_promiscuity(struct net_device *dev, int inc);
int dev_set_allmulti(struct net_device *dev, int inc); int dev_set_allmulti(struct net_device *dev, int inc);
void netdev_state_change(struct net_device *dev); void netdev_state_change(struct net_device *dev);
void __netdev_notify_peers(struct net_device *dev);
void netdev_notify_peers(struct net_device *dev); void netdev_notify_peers(struct net_device *dev);
void netdev_features_change(struct net_device *dev); void netdev_features_change(struct net_device *dev);
/* Load a device via the kmod */ /* Load a device via the kmod */
......
...@@ -1456,6 +1456,25 @@ void netdev_state_change(struct net_device *dev) ...@@ -1456,6 +1456,25 @@ void netdev_state_change(struct net_device *dev)
} }
EXPORT_SYMBOL(netdev_state_change); EXPORT_SYMBOL(netdev_state_change);
/**
* __netdev_notify_peers - notify network peers about existence of @dev,
* to be called when rtnl lock is already held.
* @dev: network device
*
* Generate traffic such that interested network peers are aware of
* @dev, such as by generating a gratuitous ARP. This may be used when
* a device wants to inform the rest of the network about some sort of
* reconfiguration such as a failover event or virtual machine
* migration.
*/
void __netdev_notify_peers(struct net_device *dev)
{
ASSERT_RTNL();
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev);
}
EXPORT_SYMBOL(__netdev_notify_peers);
/** /**
* netdev_notify_peers - notify network peers about existence of @dev * netdev_notify_peers - notify network peers about existence of @dev
* @dev: network device * @dev: network device
...@@ -1469,8 +1488,7 @@ EXPORT_SYMBOL(netdev_state_change); ...@@ -1469,8 +1488,7 @@ EXPORT_SYMBOL(netdev_state_change);
void netdev_notify_peers(struct net_device *dev) void netdev_notify_peers(struct net_device *dev)
{ {
rtnl_lock(); rtnl_lock();
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev); __netdev_notify_peers(dev);
call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev);
rtnl_unlock(); rtnl_unlock();
} }
EXPORT_SYMBOL(netdev_notify_peers); EXPORT_SYMBOL(netdev_notify_peers);
......
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