fsi: Improve master indexing
authorEddie James <eajames@linux.ibm.com>
Wed, 9 Aug 2023 18:08:13 +0000 (13:08 -0500)
committerJoel Stanley <joel@jms.id.au>
Fri, 11 Aug 2023 04:01:57 +0000 (13:31 +0930)
Master indexing is problematic if a hub is rescanned while the
root master is being rescanned. Always allocate an index for the
FSI master, and set the device name if it hasn't already been set.
Move the call to ida_free to the bottom of master unregistration
and set the number of links to 0 in case another call to scan
comes in before the device is removed.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Link: https://lore.kernel.org/r/20230809180814.151984-2-eajames@linux.ibm.com
Signed-off-by: Joel Stanley <joel@jms.id.au>
drivers/fsi/fsi-core.c

index 545581d..90872e2 100644 (file)
@@ -1309,11 +1309,21 @@ int fsi_master_register(struct fsi_master *master)
        struct device_node *np;
 
        mutex_init(&master->scan_lock);
-       master->idx = ida_alloc(&master_ida, GFP_KERNEL);
+
+       /* Alloc the requested index if it's non-zero */
+       if (master->idx) {
+               master->idx = ida_alloc_range(&master_ida, master->idx,
+                                             master->idx, GFP_KERNEL);
+       } else {
+               master->idx = ida_alloc(&master_ida, GFP_KERNEL);
+       }
+
        if (master->idx < 0)
                return master->idx;
 
-       dev_set_name(&master->dev, "fsi%d", master->idx);
+       if (!dev_name(&master->dev))
+               dev_set_name(&master->dev, "fsi%d", master->idx);
+
        master->dev.class = &fsi_master_class;
 
        rc = device_register(&master->dev);
@@ -1335,17 +1345,17 @@ EXPORT_SYMBOL_GPL(fsi_master_register);
 
 void fsi_master_unregister(struct fsi_master *master)
 {
-       trace_fsi_master_unregister(master);
+       int idx = master->idx;
 
-       if (master->idx >= 0) {
-               ida_free(&master_ida, master->idx);
-               master->idx = -1;
-       }
+       trace_fsi_master_unregister(master);
 
        mutex_lock(&master->scan_lock);
        fsi_master_unscan(master);
+       master->n_links = 0;
        mutex_unlock(&master->scan_lock);
+
        device_unregister(&master->dev);
+       ida_free(&master_ida, idx);
 }
 EXPORT_SYMBOL_GPL(fsi_master_unregister);