summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/rocker
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2016-01-27 15:16:43 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-03-03 15:07:04 -0800
commitba50e6d96f3daf3db8396cc3529f90339d9ef59a (patch)
treeac3bc9d426bfecc2ab1517403c4e55a4960abe92 /drivers/net/ethernet/rocker
parent649dc6c32e516972128502ad6a45a16b96098567 (diff)
switchdev: Require RTNL mutex to be held when sending FDB notifications
[ Upstream commit 4f2c6ae5c64c353fb1b0425e4747e5603feadba1 ] When switchdev drivers process FDB notifications from the underlying device they resolve the netdev to which the entry points to and notify the bridge using the switchdev notifier. However, since the RTNL mutex is not held there is nothing preventing the netdev from disappearing in the middle, which will cause br_switchdev_event() to dereference a non-existing netdev. Make switchdev drivers hold the lock at the beginning of the notification processing session and release it once it ends, after notifying the bridge. Also, remove switchdev_mutex and fdb_lock, as they are no longer needed when RTNL mutex is held. Fixes: 03bf0c281234 ("switchdev: introduce switchdev notifier") Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net/ethernet/rocker')
-rw-r--r--drivers/net/ethernet/rocker/rocker.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index e9f2349e98bc..52ec3d6e056a 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -3531,12 +3531,14 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
info.addr = lw->addr;
info.vid = lw->vid;
+ rtnl_lock();
if (learned && removing)
call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
lw->rocker_port->dev, &info.info);
else if (learned && !removing)
call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
lw->rocker_port->dev, &info.info);
+ rtnl_unlock();
rocker_port_kfree(lw->trans, work);
}