summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-base.c1
-rw-r--r--drivers/platform/cznic/turris-omnia-mcu-gpio.c31
2 files changed, 16 insertions, 16 deletions
diff --git a/drivers/platform/cznic/turris-omnia-mcu-base.c b/drivers/platform/cznic/turris-omnia-mcu-base.c
index e8fc0d7b3343..f0416302a1f3 100644
--- a/drivers/platform/cznic/turris-omnia-mcu-base.c
+++ b/drivers/platform/cznic/turris-omnia-mcu-base.c
@@ -403,6 +403,7 @@ static const struct of_device_id of_omnia_mcu_match[] = {
{ .compatible = "cznic,turris-omnia-mcu" },
{}
};
+MODULE_DEVICE_TABLE(of, of_omnia_mcu_match);
static struct i2c_driver omnia_mcu_driver = {
.probe = omnia_mcu_probe,
diff --git a/drivers/platform/cznic/turris-omnia-mcu-gpio.c b/drivers/platform/cznic/turris-omnia-mcu-gpio.c
index 4e430d6c3fc4..8f43bfa92373 100644
--- a/drivers/platform/cznic/turris-omnia-mcu-gpio.c
+++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c
@@ -11,7 +11,6 @@
#include <linux/bug.h>
#include <linux/cleanup.h>
#include <linux/device.h>
-#include <linux/devm-helpers.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
@@ -841,6 +840,18 @@ static void button_release_emul_fn(struct work_struct *work)
generic_handle_irq_safe(mcu->client->irq);
}
+static void omnia_disable_button_release_work(void *data)
+{
+ struct delayed_work *work = data;
+
+ /*
+ * The IRQ thread may requeue this work while the IRQ remains active.
+ * Disable and drain it before releasing the IRQ action and the MCU
+ * state used by the worker.
+ */
+ disable_delayed_work_sync(work);
+}
+
static void
fill_int_from_sts(unsigned long *rising, unsigned long *falling,
unsigned long rising_sts, unsigned long falling_sts,
@@ -1082,21 +1093,9 @@ int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)
return dev_err_probe(dev, err, "Cannot request IRQ\n");
if (!new_api) {
- /*
- * The button_release_emul_work has to be initialized before the
- * thread is requested, and on driver remove it needs to be
- * canceled before the thread is freed. Therefore we can't use
- * devm_delayed_work_autocancel() directly, because the order
- * devm_delayed_work_autocancel();
- * devm_request_threaded_irq();
- * would cause improper release order:
- * free_irq();
- * cancel_delayed_work_sync();
- * Instead we first initialize the work above, and only now
- * after IRQ is requested we add the work devm action.
- */
- err = devm_add_action(dev, devm_delayed_work_drop,
- &mcu->button_release_emul_work);
+ err = devm_add_action_or_reset(dev,
+ omnia_disable_button_release_work,
+ &mcu->button_release_emul_work);
if (err)
return err;
}