]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: ti: am65-cpsw-nuss: fix wrong devlink release order
authorLeon Romanovsky <leonro@nvidia.com>
Wed, 28 Jul 2021 07:33:45 +0000 (10:33 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Sep 2021 08:00:41 +0000 (10:00 +0200)
[ Upstream commit acf34954efd17d4f65c7bb3e614381e6afc33222 ]

The commit that introduced devlink support released devlink resources in
wrong order, that made an unwind flow to be asymmetrical. In addition,
the am65-cpsw-nuss used internal to devlink core field - registered.

In order to fix the unwind flow and remove such access to the
registered field, rewrite the code to call devlink_port_unregister only
on registered ports.

Fixes: 58356eb31d60 ("net: ti: am65-cpsw-nuss: Add devlink support")
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/ti/am65-cpsw-nuss.c

index 67a08cbba859de74fedc3e20210f417e603d86a9..fb58fc4707738503208a78e6c2aefbd9e47e7a4d 100644 (file)
@@ -2388,21 +2388,6 @@ static const struct devlink_param am65_cpsw_devlink_params[] = {
                             am65_cpsw_dl_switch_mode_set, NULL),
 };
 
-static void am65_cpsw_unregister_devlink_ports(struct am65_cpsw_common *common)
-{
-       struct devlink_port *dl_port;
-       struct am65_cpsw_port *port;
-       int i;
-
-       for (i = 1; i <= common->port_num; i++) {
-               port = am65_common_get_port(common, i);
-               dl_port = &port->devlink_port;
-
-               if (dl_port->registered)
-                       devlink_port_unregister(dl_port);
-       }
-}
-
 static int am65_cpsw_nuss_register_devlink(struct am65_cpsw_common *common)
 {
        struct devlink_port_attrs attrs = {};
@@ -2464,7 +2449,12 @@ static int am65_cpsw_nuss_register_devlink(struct am65_cpsw_common *common)
        return ret;
 
 dl_port_unreg:
-       am65_cpsw_unregister_devlink_ports(common);
+       for (i = i - 1; i >= 1; i--) {
+               port = am65_common_get_port(common, i);
+               dl_port = &port->devlink_port;
+
+               devlink_port_unregister(dl_port);
+       }
 dl_unreg:
        devlink_unregister(common->devlink);
 dl_free:
@@ -2475,6 +2465,17 @@ dl_free:
 
 static void am65_cpsw_unregister_devlink(struct am65_cpsw_common *common)
 {
+       struct devlink_port *dl_port;
+       struct am65_cpsw_port *port;
+       int i;
+
+       for (i = 1; i <= common->port_num; i++) {
+               port = am65_common_get_port(common, i);
+               dl_port = &port->devlink_port;
+
+               devlink_port_unregister(dl_port);
+       }
+
        if (!AM65_CPSW_IS_CPSW2G(common) &&
            IS_ENABLED(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV)) {
                devlink_params_unpublish(common->devlink);
@@ -2482,7 +2483,6 @@ static void am65_cpsw_unregister_devlink(struct am65_cpsw_common *common)
                                          ARRAY_SIZE(am65_cpsw_devlink_params));
        }
 
-       am65_cpsw_unregister_devlink_ports(common);
        devlink_unregister(common->devlink);
        devlink_free(common->devlink);
 }