summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pwm/core.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index c6228843a1a7..f1ded8ce5ea4 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -433,24 +433,15 @@ static void pwm_apply_debug(struct pwm_device *pwm,
}
/**
- * pwm_apply_might_sleep() - atomically apply a new state to a PWM device
+ * __pwm_apply() - atomically apply a new state to a PWM device
* @pwm: PWM device
* @state: new state to apply
*/
-int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
+static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state)
{
struct pwm_chip *chip;
int err;
- /*
- * Some lowlevel driver's implementations of .apply() make use of
- * mutexes, also with some drivers only returning when the new
- * configuration is active calling pwm_apply_might_sleep() from atomic context
- * is a bad idea. So make it explicit that calling this function might
- * sleep.
- */
- might_sleep();
-
if (!pwm || !state || !state->period ||
state->duty_cycle > state->period)
return -EINVAL;
@@ -479,9 +470,58 @@ int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
return 0;
}
+
+/**
+ * pwm_apply_might_sleep() - atomically apply a new state to a PWM device
+ * Cannot be used in atomic context.
+ * @pwm: PWM device
+ * @state: new state to apply
+ */
+int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
+{
+ int err;
+
+ /*
+ * Some lowlevel driver's implementations of .apply() make use of
+ * mutexes, also with some drivers only returning when the new
+ * configuration is active calling pwm_apply_might_sleep() from atomic context
+ * is a bad idea. So make it explicit that calling this function might
+ * sleep.
+ */
+ might_sleep();
+
+ if (IS_ENABLED(CONFIG_PWM_DEBUG) && pwm->chip->atomic) {
+ /*
+ * Catch any drivers that have been marked as atomic but
+ * that will sleep anyway.
+ */
+ non_block_start();
+ err = __pwm_apply(pwm, state);
+ non_block_end();
+ } else {
+ err = __pwm_apply(pwm, state);
+ }
+
+ return err;
+}
EXPORT_SYMBOL_GPL(pwm_apply_might_sleep);
/**
+ * pwm_apply_atomic() - apply a new state to a PWM device from atomic context
+ * Not all PWM devices support this function, check with pwm_might_sleep().
+ * @pwm: PWM device
+ * @state: new state to apply
+ */
+int pwm_apply_atomic(struct pwm_device *pwm, const struct pwm_state *state)
+{
+ WARN_ONCE(!pwm->chip->atomic,
+ "sleeping PWM driver used in atomic context\n");
+
+ return __pwm_apply(pwm, state);
+}
+EXPORT_SYMBOL_GPL(pwm_apply_atomic);
+
+/**
* pwm_capture() - capture and report a PWM signal
* @pwm: PWM device
* @result: structure to fill with capture result