summaryrefslogtreecommitdiff
path: root/drivers/mux/core.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2021-11-06 21:49:33 +0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2021-11-06 21:49:33 +0300
commit7f9f879243d6cf5d2d60d12065e93189cc343387 (patch)
treee74619a16f8291f7225ee9877cf93e530243e0d3 /drivers/mux/core.c
parent32f7aa2731b24ad8393f26d63df959d74844345f (diff)
parentfe91c4725aeed35023ba4f7a1e1adfebb6878c23 (diff)
downloadlinux-7f9f879243d6cf5d2d60d12065e93189cc343387.tar.xz
Merge remote-tracking branch 'torvalds/master' into perf/core
To pick up some tools/perf/ patches that went via tip/perf/core, such as: tools/perf: Add mem_hops field in perf_mem_data_src structure Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'drivers/mux/core.c')
-rw-r--r--drivers/mux/core.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index 1fb22388e7e0..22f4709768d1 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -9,6 +9,7 @@
#define pr_fmt(fmt) "mux-core: " fmt
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
@@ -116,6 +117,7 @@ struct mux_chip *mux_chip_alloc(struct device *dev,
sema_init(&mux->lock, 1);
mux->cached_state = MUX_CACHE_UNKNOWN;
mux->idle_state = MUX_IDLE_AS_IS;
+ mux->last_change = ktime_get();
}
device_initialize(&mux_chip->dev);
@@ -129,6 +131,8 @@ static int mux_control_set(struct mux_control *mux, int state)
int ret = mux->chip->ops->set(mux, state);
mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;
+ if (ret >= 0)
+ mux->last_change = ktime_get();
return ret;
}
@@ -314,10 +318,25 @@ static int __mux_control_select(struct mux_control *mux, int state)
return ret;
}
+static void mux_control_delay(struct mux_control *mux, unsigned int delay_us)
+{
+ ktime_t delayend;
+ s64 remaining;
+
+ if (!delay_us)
+ return;
+
+ delayend = ktime_add_us(mux->last_change, delay_us);
+ remaining = ktime_us_delta(delayend, ktime_get());
+ if (remaining > 0)
+ fsleep(remaining);
+}
+
/**
- * mux_control_select() - Select the given multiplexer state.
+ * mux_control_select_delay() - Select the given multiplexer state.
* @mux: The mux-control to request a change of state from.
* @state: The new requested state.
+ * @delay_us: The time to delay (in microseconds) if the mux state is changed.
*
* On successfully selecting the mux-control state, it will be locked until
* there is a call to mux_control_deselect(). If the mux-control is already
@@ -331,7 +350,8 @@ static int __mux_control_select(struct mux_control *mux, int state)
* Return: 0 when the mux-control state has the requested state or a negative
* errno on error.
*/
-int mux_control_select(struct mux_control *mux, unsigned int state)
+int mux_control_select_delay(struct mux_control *mux, unsigned int state,
+ unsigned int delay_us)
{
int ret;
@@ -340,18 +360,21 @@ int mux_control_select(struct mux_control *mux, unsigned int state)
return ret;
ret = __mux_control_select(mux, state);
+ if (ret >= 0)
+ mux_control_delay(mux, delay_us);
if (ret < 0)
up(&mux->lock);
return ret;
}
-EXPORT_SYMBOL_GPL(mux_control_select);
+EXPORT_SYMBOL_GPL(mux_control_select_delay);
/**
- * mux_control_try_select() - Try to select the given multiplexer state.
+ * mux_control_try_select_delay() - Try to select the given multiplexer state.
* @mux: The mux-control to request a change of state from.
* @state: The new requested state.
+ * @delay_us: The time to delay (in microseconds) if the mux state is changed.
*
* On successfully selecting the mux-control state, it will be locked until
* mux_control_deselect() called.
@@ -363,7 +386,8 @@ EXPORT_SYMBOL_GPL(mux_control_select);
* Return: 0 when the mux-control state has the requested state or a negative
* errno on error. Specifically -EBUSY if the mux-control is contended.
*/
-int mux_control_try_select(struct mux_control *mux, unsigned int state)
+int mux_control_try_select_delay(struct mux_control *mux, unsigned int state,
+ unsigned int delay_us)
{
int ret;
@@ -371,13 +395,15 @@ int mux_control_try_select(struct mux_control *mux, unsigned int state)
return -EBUSY;
ret = __mux_control_select(mux, state);
+ if (ret >= 0)
+ mux_control_delay(mux, delay_us);
if (ret < 0)
up(&mux->lock);
return ret;
}
-EXPORT_SYMBOL_GPL(mux_control_try_select);
+EXPORT_SYMBOL_GPL(mux_control_try_select_delay);
/**
* mux_control_deselect() - Deselect the previously selected multiplexer state.