diff options
author | Eddie James <eajames@linux.ibm.com> | 2023-08-09 21:08:13 +0300 |
---|---|---|
committer | Joel Stanley <joel@jms.id.au> | 2023-08-11 07:01:57 +0300 |
commit | adde0e112c6365c6a930a3d8cd0c7a4accd55adc (patch) | |
tree | d250f1b75675785b5c941651f617c3c630d3e3f8 /drivers/fsi/fsi-core.c | |
parent | 85f4e899de32ba3cd27fa601b17a700c85633626 (diff) | |
download | linux-adde0e112c6365c6a930a3d8cd0c7a4accd55adc.tar.xz |
fsi: Improve master indexing
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>
Diffstat (limited to 'drivers/fsi/fsi-core.c')
-rw-r--r-- | drivers/fsi/fsi-core.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 545581d83a33..90872e2e78d1 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c @@ -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); |