From 73e3fcabc0f09bac77d6fd43d81c7ef661a953a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 2 Jan 2023 10:34:32 +0100 Subject: [PATCH] usb: dfu: Schedule timer handler from USB workqueue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use k_work_delayable instead of k_timer in order to execute timeout in USB workqueue context instead of ISR context. This fixes Will-Detach on targets where usb_dc_detach() uses functions not allowed in ISR context, e.g. nrfx usb_dc_detach() acquires mutex. Fixes: c27d48c89ae6 ("usb: dfu: Support DFU with WinUSB on Windows") Signed-off-by: Tomasz Moń --- subsys/usb/device/class/dfu/usb_dfu.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/subsys/usb/device/class/dfu/usb_dfu.c b/subsys/usb/device/class/dfu/usb_dfu.c index 87d703205eb..07c73194d0b 100644 --- a/subsys/usb/device/class/dfu/usb_dfu.c +++ b/subsys/usb/device/class/dfu/usb_dfu.c @@ -91,7 +91,7 @@ LOG_MODULE_REGISTER(usb_dfu, CONFIG_USB_DEVICE_LOG_LEVEL); static struct k_poll_event dfu_event; static struct k_poll_signal dfu_signal; -static struct k_timer dfu_timer; +static struct k_work_delayable dfu_timer_work; static struct k_work dfu_work; @@ -417,8 +417,10 @@ static void dfu_enter_idle(void) } } -static void dfu_timer_expired(struct k_timer *timer) +static void dfu_timer_work_handler(struct k_work *item) { + ARG_UNUSED(item); + if (dfu_data.state == appDETACH) { if (IS_ENABLED(CONFIG_USB_DFU_WILL_DETACH)) { if (usb_dc_detach()) { @@ -693,7 +695,7 @@ static int dfu_class_handle_to_device(struct usb_setup_packet *setup, /* Begin detach timeout timer */ timeout = MIN(setup->wValue, CONFIG_USB_DFU_DETACH_TIMEOUT); } - k_timer_start(&dfu_timer, K_MSEC(timeout), K_FOREVER); + k_work_reschedule_for_queue(&USB_WORK_Q, &dfu_timer_work, K_MSEC(timeout)); break; default: LOG_DBG("Unsupported bmRequestType 0x%02x bRequest 0x%02x", @@ -747,7 +749,7 @@ static void dfu_status_cb(struct usb_cfg_data *cfg, LOG_DBG("USB device reset detected, state %d", dfu_data.state); if (!IS_ENABLED(CONFIG_USB_DFU_WILL_DETACH)) { /* Stop the appDETACH timeout timer */ - k_timer_stop(&dfu_timer); + k_work_cancel_delayable(&dfu_timer_work); if (dfu_data.state == appDETACH) { dfu_enter_idle(); } @@ -904,7 +906,7 @@ static int usb_dfu_init(const struct device *dev) k_work_init(&dfu_work, dfu_work_handler); k_poll_signal_init(&dfu_signal); - k_timer_init(&dfu_timer, dfu_timer_expired, NULL); + k_work_init_delayable(&dfu_timer_work, dfu_timer_work_handler); #ifdef CONFIG_USB_DFU_REBOOT k_work_init_delayable(&reboot_work, reboot_work_handler);