FAILED: patch "[PATCH] i2c: core: Lock address during client device instantiation" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 8d3cefaf659265aa82b0373a563fdb9d16a2b947
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024100713-creatable-lapped-c0b3@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
8d3cefaf6592 ("i2c: core: Lock address during client device instantiation") 73febd775bdb ("i2c: create debugfs entry per adapter")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8d3cefaf659265aa82b0373a563fdb9d16a2b947 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <[email protected]>
Date: Thu, 15 Aug 2024 21:44:50 +0200
Subject: [PATCH] i2c: core: Lock address during client device instantiation
Krzysztof reported an issue [0] which is caused by parallel attempts to instantiate the same I2C client device. This can happen if driver supports auto-detection, but certain devices are also instantiated explicitly.
The original change isn't actually wrong, it just revealed that I2C core isn't prepared yet to handle this scenario.
Calls to i2c_new_client_device() can be nested, therefore we can't use a simple mutex here. Parallel instantiation of devices at different addresses is ok, so we just have to prevent parallel instantiation at the same address. We can use a bitmap with one bit per 7-bit I2C client address, and atomic bit operations to set/check/clear bits.
Now a parallel attempt to instantiate a device at the same address will result in -EBUSY being returned, avoiding the "sysfs: cannot create duplicate filename" splash.
Note: This patch version includes small cosmetic changes to the Tested-by
version, only functional change is that address locking is supported for slave addresses too.
[0] https://lore.kernel.org/linux-i2c/[email protected]/T/#m12706546e8e2414d8f1a0dc61c53393f731685cc
drivers/i2c/i2c-core-base.c +28 -0
@@ -915,6 +915,27 @@ int i2c_dev_irq_from_resources(const struct resource *resources,return 0 ; } +/* +* Serialize device instantiation in case it can be instantiated explicitly +* and by auto-detection +*/ +static int i2c_lock_addr (struct i2c_adapter *adap,unsigned short addr, +unsigned short flags) +{ +if (!(flags &I2C_CLIENT_TEN ) && +test_and_set_bit (addr, adap->addrs_in_instantiation)) +return -EBUSY ; + +return 0 ; +} + +static void i2c_unlock_addr (struct i2c_adapter *adap,unsigned short addr, +unsigned short flags) +{ +if (!(flags &I2C_CLIENT_TEN )) +clear_bit (addr, adap->addrs_in_instantiation); +} +/** * i2c_new_client_device - instantiate an i2c device * @adap: the adapter managing the device
@@ -962,6 +983,10 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf goto out_err_silent; } + status =i2c_lock_addr (adap, client->addr, client->flags); +if (status) + goto out_err_silent; +/* Check for address business */ status =i2c_check_addr_busy (adap,i2c_encode_flags_to_addr (client));if (status)
@@ -993,6 +1018,8 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *infdev_dbg (&adap->dev,"client [%s] registered with bus id %s\n" , client->name,dev_name (&client->dev)); +i2c_unlock_addr (adap, client->addr, client->flags); +return client; out_remove_swnode:
@@ -1004,6 +1031,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *infdev_err (&adap->dev,"Failed to register i2c client %s at 0x%02x (%d)\n" , client->name, client->addr, status); +i2c_unlock_addr (adap, client->addr, client->flags); out_err_silent:if (need_put)put_device (&client->dev);
include/linux/i2c.h +3 -0
@@ -761,6 +761,9 @@ struct i2c_adapter {struct regulator *bus_regulator;struct dentry *debugfs; + +/* 7bit address space */ +DECLARE_BITMAP (addrs_in_instantiation,1 <<7 ); };#define to_i2c_adapter (d) container_of(d, struct i2c_adapter, dev)