]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
libertas: register sysfs groups properly
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 May 2021 11:57:20 +0000 (13:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Jun 2021 06:22:08 +0000 (08:22 +0200)
[ Upstream commit 7e79b38fe9a403b065ac5915465f620a8fb3de84 ]

The libertas driver was trying to register sysfs groups "by hand" which
causes them to be created _after_ the device is initialized and
announced to userspace, which causes races and can prevent userspace
tools from seeing the sysfs files correctly.

Fix this up by using the built-in sysfs_groups pointers in struct
net_device which were created for this very reason, fixing the race
condition, and properly allowing for any error that might have occured
to be handled properly.

Cc: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210503115736.2104747-54-gregkh@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/libertas/mesh.c

index d0c881dd584677f18c551657d351b6bee435da5f..f1e9cbcfdc168bf12993698bcbf0e765259e6f2f 100644 (file)
@@ -797,19 +797,6 @@ static const struct attribute_group mesh_ie_group = {
        .attrs = mesh_ie_attrs,
 };
 
-static void lbs_persist_config_init(struct net_device *dev)
-{
-       int ret;
-       ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
-       ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
-}
-
-static void lbs_persist_config_remove(struct net_device *dev)
-{
-       sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
-       sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
-}
-
 
 /***************************************************************************
  * Initializing and starting, stopping mesh
@@ -1021,6 +1008,10 @@ static int lbs_add_mesh(struct lbs_private *priv)
        SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
 
        mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+       mesh_dev->sysfs_groups[0] = &lbs_mesh_attr_group;
+       mesh_dev->sysfs_groups[1] = &boot_opts_group;
+       mesh_dev->sysfs_groups[2] = &mesh_ie_group;
+
        /* Register virtual mesh interface */
        ret = register_netdev(mesh_dev);
        if (ret) {
@@ -1028,19 +1019,10 @@ static int lbs_add_mesh(struct lbs_private *priv)
                goto err_free_netdev;
        }
 
-       ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-       if (ret)
-               goto err_unregister;
-
-       lbs_persist_config_init(mesh_dev);
-
        /* Everything successful */
        ret = 0;
        goto done;
 
-err_unregister:
-       unregister_netdev(mesh_dev);
-
 err_free_netdev:
        free_netdev(mesh_dev);
 
@@ -1063,8 +1045,6 @@ void lbs_remove_mesh(struct lbs_private *priv)
        lbs_deb_enter(LBS_DEB_MESH);
        netif_stop_queue(mesh_dev);
        netif_carrier_off(mesh_dev);
-       sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-       lbs_persist_config_remove(mesh_dev);
        unregister_netdev(mesh_dev);
        priv->mesh_dev = NULL;
        kfree(mesh_dev->ieee80211_ptr);