s390/qeth: reduce rtnl locking for switchdev events
authorJulian Wiedmann <jwi@linux.ibm.com>
Tue, 17 Nov 2020 16:15:13 +0000 (17:15 +0100)
committerJakub Kicinski <kuba@kernel.org>
Thu, 19 Nov 2020 01:34:18 +0000 (17:34 -0800)
call_switchdev_notifiers() doesn't require holding the RTNL lock since
commit ff5cf100110c ("net: switchdev: Change notifier chain to be atomic").

We still need it for the "lost event" slow path, to avoid racing against
a concurrent .ndo_bridge_setlink().

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/s390/net/qeth_l2_main.c

index 28f6dda..daeb837 100644 (file)
@@ -737,8 +737,6 @@ static void qeth_l2_dev2br_an_set_cb(void *priv,
  *
  *     On enable, emits a series of address notifications for all
  *     currently registered hosts.
- *
- *     Must be called under rtnl_lock
  */
 static int qeth_l2_dev2br_an_set(struct qeth_card *card, bool enable)
 {
@@ -1289,16 +1287,19 @@ static void qeth_l2_dev2br_worker(struct work_struct *work)
        if (READ_ONCE(card->info.pnso_mode) == QETH_PNSO_NONE)
                goto free;
 
-       /* Potential re-config in progress, try again later: */
-       if (!rtnl_trylock()) {
-               queue_delayed_work(card->event_wq, dwork,
-                                  msecs_to_jiffies(100));
-               return;
-       }
-       if (!netif_device_present(card->dev))
-               goto out_unlock;
-
        if (data->ac_event.lost_event_mask) {
+               /* Potential re-config in progress, try again later: */
+               if (!rtnl_trylock()) {
+                       queue_delayed_work(card->event_wq, dwork,
+                                          msecs_to_jiffies(100));
+                       return;
+               }
+
+               if (!netif_device_present(card->dev)) {
+                       rtnl_unlock();
+                       goto free;
+               }
+
                QETH_DBF_MESSAGE(3,
                                 "Address change notification overflow on device %x\n",
                                 CARD_DEVID(card));
@@ -1328,6 +1329,8 @@ static void qeth_l2_dev2br_worker(struct work_struct *work)
                                         "Address Notification resynced on device %x\n",
                                         CARD_DEVID(card));
                }
+
+               rtnl_unlock();
        } else {
                for (i = 0; i < data->ac_event.num_entries; i++) {
                        struct qeth_ipacmd_addr_change_entry *entry =
@@ -1339,9 +1342,6 @@ static void qeth_l2_dev2br_worker(struct work_struct *work)
                }
        }
 
-out_unlock:
-       rtnl_unlock();
-
 free:
        kfree(data);
 }
@@ -2310,11 +2310,8 @@ static void qeth_l2_set_offline(struct qeth_card *card)
                card->state = CARD_STATE_DOWN;
 
        qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
-       if (priv->brport_features & BR_LEARNING_SYNC) {
-               rtnl_lock();
+       if (priv->brport_features & BR_LEARNING_SYNC)
                qeth_l2_dev2br_fdb_flush(card);
-               rtnl_unlock();
-       }
 }
 
 /* Returns zero if the command is successfully "consumed" */