diff options
author | Jae Hyun Yoo <jae.hyun.yoo@intel.com> | 2021-06-24 21:01:36 +0300 |
---|---|---|
committer | Yoo, Jae Hyun <jae.hyun.yoo@intel.com> | 2021-06-28 20:37:30 +0300 |
commit | ab0d43fcc078edf3123887f9bff1e8ef7d87e641 (patch) | |
tree | 72e79e047d928ed2300533dbc7688cfb54570474 | |
parent | fd3a181afd8bb82a82cc32c781646719775bd812 (diff) | |
download | linux-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.c | 13 | ||||
-rw-r--r-- | drivers/i2c/i2c-mux.c | 14 | ||||
-rw-r--r-- | include/linux/i2c-mux.h | 3 | ||||
-rw-r--r-- | include/linux/i2c.h | 3 |
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) |