summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJae Hyun Yoo <jae.hyun.yoo@intel.com>2021-06-24 21:01:36 +0300
committerYoo, Jae Hyun <jae.hyun.yoo@intel.com>2021-06-28 20:37:30 +0300
commitab0d43fcc078edf3123887f9bff1e8ef7d87e641 (patch)
tree72e79e047d928ed2300533dbc7688cfb54570474
parentfd3a181afd8bb82a82cc32c781646719775bd812 (diff)
downloadlinux-ab0d43fcc078edf3123887f9bff1e8ef7d87e641.tar.xz
fixup! i2c: Add mux hold/unhold msg types
It replaces timer callback with delayed work to avoid deadlock. Tested: Passed over weekend stress test. Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> Change-Id: I123cacabe7c1a5988f6356deeee03a6996b87141
-rw-r--r--drivers/i2c/i2c-core-base.c13
-rw-r--r--drivers/i2c/i2c-mux.c14
-rw-r--r--include/linux/i2c-mux.h3
-rw-r--r--include/linux/i2c.h3
4 files changed, 18 insertions, 15 deletions
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index eb632a569203..a46ca6259019 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1395,20 +1395,21 @@ EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
static void i2c_adapter_hold(struct i2c_adapter *adapter, unsigned long timeout)
{
mutex_lock(&adapter->hold_lock);
- mod_timer(&adapter->hold_timer, jiffies + timeout);
+ schedule_delayed_work(&adapter->unhold_work, timeout);
}
static void i2c_adapter_unhold(struct i2c_adapter *adapter)
{
- del_timer_sync(&adapter->hold_timer);
+ cancel_delayed_work_sync(&adapter->unhold_work);
mutex_unlock(&adapter->hold_lock);
}
-static void i2c_adapter_hold_timer_callback(struct timer_list *t)
+static void i2c_adapter_unhold_work(struct work_struct *work)
{
- struct i2c_adapter *adapter = from_timer(adapter, t, hold_timer);
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct i2c_adapter *adapter = container_of(dwork, struct i2c_adapter,
+ unhold_work);
- del_timer(&adapter->hold_timer);
mutex_unlock(&adapter->hold_lock);
}
@@ -1505,7 +1506,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
mutex_unlock(&core_lock);
mutex_init(&adap->hold_lock);
- timer_setup(&adap->hold_timer, i2c_adapter_hold_timer_callback, 0);
+ INIT_DELAYED_WORK(&adap->unhold_work, i2c_adapter_unhold_work);
return 0;
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 8dd2fc342eb0..dc95c40dfc30 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -27,7 +27,6 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
-#include <linux/timer.h>
/* multiplexer per channel data */
struct i2c_mux_priv {
@@ -40,20 +39,21 @@ struct i2c_mux_priv {
static void i2c_mux_hold(struct i2c_mux_core *muxc, unsigned long timeout)
{
mutex_lock(&muxc->hold_lock);
- mod_timer(&muxc->hold_timer, jiffies + timeout);
+ schedule_delayed_work(&muxc->unhold_work, timeout);
}
static void i2c_mux_unhold(struct i2c_mux_core *muxc)
{
- del_timer_sync(&muxc->hold_timer);
+ cancel_delayed_work_sync(&muxc->unhold_work);
mutex_unlock(&muxc->hold_lock);
}
-static void i2c_mux_hold_timer_callback(struct timer_list *t)
+static void i2c_mux_unhold_work(struct work_struct *work)
{
- struct i2c_mux_core *muxc = from_timer(muxc, t, hold_timer);
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct i2c_mux_core *muxc = container_of(dwork, struct i2c_mux_core,
+ unhold_work);
- del_timer(&muxc->hold_timer);
mutex_unlock(&muxc->hold_lock);
}
@@ -353,7 +353,7 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
muxc->max_adapters = max_adapters;
mutex_init(&muxc->hold_lock);
- timer_setup(&muxc->hold_timer, i2c_mux_hold_timer_callback, 0);
+ INIT_DELAYED_WORK(&muxc->unhold_work, i2c_mux_unhold_work);
return muxc;
}
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index f0866b5522b6..43c40680d8c5 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -14,6 +14,7 @@
#ifdef __KERNEL__
#include <linux/bitops.h>
+#include <linux/workqueue.h>
struct i2c_mux_core {
struct i2c_adapter *parent;
@@ -28,7 +29,7 @@ struct i2c_mux_core {
int (*deselect)(struct i2c_mux_core *, u32 chan_id);
struct mutex hold_lock; /* mutex for channel holding */
- struct timer_list hold_timer;
+ struct delayed_work unhold_work;
int num_adapters;
int max_adapters;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 05c792509c82..0d996b722b75 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -19,6 +19,7 @@
#include <linux/irqdomain.h> /* for Host Notify IRQ */
#include <linux/of.h> /* for struct device_node */
#include <linux/swab.h> /* for swab16 */
+#include <linux/workqueue.h>
#include <uapi/linux/i2c.h>
extern struct bus_type i2c_bus_type;
@@ -730,7 +731,7 @@ struct i2c_adapter {
* has these individually.
*/
struct mutex hold_lock; /* mutex for bus holding */
- struct timer_list hold_timer;
+ struct delayed_work unhold_work;
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)