summaryrefslogtreecommitdiff
path: root/drivers/fsi
diff options
context:
space:
mode:
authorEddie James <eajames@linux.ibm.com>2023-08-09 13:08:13 -0500
committerJoel Stanley <joel@jms.id.au>2023-08-11 13:31:57 +0930
commitadde0e112c6365c6a930a3d8cd0c7a4accd55adc (patch)
treed250f1b75675785b5c941651f617c3c630d3e3f8 /drivers/fsi
parent85f4e899de32ba3cd27fa601b17a700c85633626 (diff)
downloadlwn-adde0e112c6365c6a930a3d8cd0c7a4accd55adc.tar.gz
lwn-adde0e112c6365c6a930a3d8cd0c7a4accd55adc.zip
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')
-rw-r--r--drivers/fsi/fsi-core.c24
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);