]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
i2c: core: clean up bus id allocation
authorJohan Hovold <johan@kernel.org>
Mon, 11 May 2026 14:37:14 +0000 (16:37 +0200)
committerWolfram Sang <wsa+renesas@sang-engineering.com>
Sat, 30 May 2026 21:57:19 +0000 (23:57 +0200)
Clean up bus id allocation by using a common helper and deferring it
until it is needed during adapter registration.

Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
drivers/i2c/i2c-core-base.c

index 38f425aecef869ceda41403696e0176e8db16120..2cd384433d83e9b530a1e3b3a95e3501125391fb 100644 (file)
@@ -1517,23 +1517,48 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
 }
 EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
 
+static int i2c_allocate_adapter_id(struct i2c_adapter *adap)
+{
+       int id, start, end;
+
+       if (adap->nr == -1) {
+               start = __i2c_first_dynamic_bus_num;
+               end = 0;
+       } else {
+               start = adap->nr;
+               end = adap->nr + 1;
+       }
+
+       mutex_lock(&core_lock);
+       id = idr_alloc(&i2c_adapter_idr, NULL, start, end, GFP_KERNEL);
+       mutex_unlock(&core_lock);
+       if (id < 0) {
+               if (adap->nr != -1 && id == -ENOSPC)
+                       id = -EBUSY;
+               pr_err("adapter '%s': failed to allocate id: %d\n", adap->name, id);
+               return id;
+       }
+
+       adap->nr = id;
+
+       return 0;
+}
+
 static int i2c_register_adapter(struct i2c_adapter *adap)
 {
-       int res = -EINVAL;
+       int res;
 
        /* Can't register until after driver model init */
-       if (WARN_ON(!is_registered)) {
-               res = -EAGAIN;
-               goto out_list;
-       }
+       if (WARN_ON(!is_registered))
+               return -EAGAIN;
 
        /* Sanity checks */
        if (WARN(!adap->name[0], "i2c adapter has no name"))
-               goto out_list;
+               return -EINVAL;
 
        if (!adap->algo) {
                pr_err("adapter '%s': no algo supplied!\n", adap->name);
-               goto out_list;
+               return -EINVAL;
        }
 
        if (!adap->lock_ops)
@@ -1554,13 +1579,17 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
        if (res) {
                pr_err("adapter '%s': can't create Host Notify IRQs (%d)\n",
                       adap->name, res);
-               goto out_list;
+               return res;
        }
 
-       res = dev_set_name(&adap->dev, "i2c-%d", adap->nr);
+       res = i2c_allocate_adapter_id(adap);
        if (res)
                goto err_remove_irq_domain;
 
+       res = dev_set_name(&adap->dev, "i2c-%d", adap->nr);
+       if (res)
+               goto err_free_id;
+
        adap->dev.bus = &i2c_bus_type;
        adap->dev.type = &i2c_adapter_type;
        device_initialize(&adap->dev);
@@ -1624,33 +1653,14 @@ err_put_adap:
        init_completion(&adap->dev_released);
        put_device(&adap->dev);
        wait_for_completion(&adap->dev_released);
-err_remove_irq_domain:
-       i2c_host_notify_irq_teardown(adap);
-out_list:
+err_free_id:
        mutex_lock(&core_lock);
        idr_remove(&i2c_adapter_idr, adap->nr);
        mutex_unlock(&core_lock);
-       return res;
-}
-
-/**
- * __i2c_add_numbered_adapter - i2c_add_numbered_adapter where nr is never -1
- * @adap: the adapter to register (with adap->nr initialized)
- * Context: can sleep
- *
- * See i2c_add_numbered_adapter() for details.
- */
-static int __i2c_add_numbered_adapter(struct i2c_adapter *adap)
-{
-       int id;
-
-       mutex_lock(&core_lock);
-       id = idr_alloc(&i2c_adapter_idr, NULL, adap->nr, adap->nr + 1, GFP_KERNEL);
-       mutex_unlock(&core_lock);
-       if (WARN(id < 0, "couldn't get idr"))
-               return id == -ENOSPC ? -EBUSY : id;
+err_remove_irq_domain:
+       i2c_host_notify_irq_teardown(adap);
 
-       return i2c_register_adapter(adap);
+       return res;
 }
 
 /**
@@ -1673,17 +1683,8 @@ int i2c_add_adapter(struct i2c_adapter *adapter)
        int id;
 
        id = of_alias_get_id(dev->of_node, "i2c");
-       if (id >= 0) {
-               adapter->nr = id;
-               return __i2c_add_numbered_adapter(adapter);
-       }
-
-       mutex_lock(&core_lock);
-       id = idr_alloc(&i2c_adapter_idr, NULL,
-                      __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
-       mutex_unlock(&core_lock);
-       if (WARN(id < 0, "couldn't get idr"))
-               return id;
+       if (id < 0)
+               id = -1;
 
        adapter->nr = id;
 
@@ -1719,7 +1720,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap)
        if (adap->nr == -1) /* -1 means dynamically assign bus id */
                return i2c_add_adapter(adap);
 
-       return __i2c_add_numbered_adapter(adap);
+       return i2c_register_adapter(adap);
 }
 EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);