From: Sasha Levin Date: Sun, 3 Nov 2024 20:24:39 +0000 (-0500) Subject: Fixes for 6.1 X-Git-Tag: v4.19.323~99 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=37b159092d669a74fd0f90f784e9ed5f595ae7cc;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/series b/queue-6.1/series index e2f46290bb9..716f64e708e 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -63,3 +63,7 @@ cifs-fix-creating-native-symlinks-pointing-to-curren.patch net-amd-mvme147-fix-probe-banner-message.patch nfs-remove-revoked-delegation-from-server-s-delegati.patch misc-sgi-gru-don-t-disable-preemption-in-gru-driver.patch +usb-gadget-dummy_hcd-switch-to-hrtimer-transfer-sche.patch +usb-gadget-dummy_hcd-set-transfer-interval-to-1-micr.patch +usb-gadget-dummy_hcd-execute-hrtimer-callback-in-sof.patch +usb-gadget-dummy-hcd-fix-task-hung-problem.patch diff --git a/queue-6.1/usb-gadget-dummy-hcd-fix-task-hung-problem.patch b/queue-6.1/usb-gadget-dummy-hcd-fix-task-hung-problem.patch new file mode 100644 index 00000000000..abab33fe01d --- /dev/null +++ b/queue-6.1/usb-gadget-dummy-hcd-fix-task-hung-problem.patch @@ -0,0 +1,124 @@ +From 85f088c658432975d8da3a9e795e4232918db101 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Oct 2024 11:44:45 -0400 +Subject: USB: gadget: dummy-hcd: Fix "task hung" problem + +From: Alan Stern + +[ Upstream commit 5189df7b8088268012882c220d6aca4e64981348 ] + +The syzbot fuzzer has been encountering "task hung" problems ever +since the dummy-hcd driver was changed to use hrtimers instead of +regular timers. It turns out that the problems are caused by a subtle +difference between the timer_pending() and hrtimer_active() APIs. + +The changeover blindly replaced the first by the second. However, +timer_pending() returns True when the timer is queued but not when its +callback is running, whereas hrtimer_active() returns True when the +hrtimer is queued _or_ its callback is running. This difference +occasionally caused dummy_urb_enqueue() to think that the callback +routine had not yet started when in fact it was almost finished. As a +result the hrtimer was not restarted, which made it impossible for the +driver to dequeue later the URB that was just enqueued. This caused +usb_kill_urb() to hang, and things got worse from there. + +Since hrtimers have no API for telling when they are queued and the +callback isn't running, the driver must keep track of this for itself. +That's what this patch does, adding a new "timer_pending" flag and +setting or clearing it at the appropriate times. + +Reported-by: syzbot+f342ea16c9d06d80b585@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-usb/6709234e.050a0220.3e960.0011.GAE@google.com/ +Tested-by: syzbot+f342ea16c9d06d80b585@syzkaller.appspotmail.com +Signed-off-by: Alan Stern +Fixes: a7f3813e589f ("usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler") +Cc: Marcello Sylvester Bauer +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/2dab644e-ef87-4de8-ac9a-26f100b2c609@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/dummy_hcd.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index 019e8f3007c94..6e18e8e76e8b9 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -254,6 +254,7 @@ struct dummy_hcd { + u32 stream_en_ep; + u8 num_stream[30 / 2]; + ++ unsigned timer_pending:1; + unsigned active:1; + unsigned old_active:1; + unsigned resuming:1; +@@ -1304,9 +1305,11 @@ static int dummy_urb_enqueue( + urb->error_count = 1; /* mark as a new urb */ + + /* kick the scheduler, it'll do the rest */ +- if (!hrtimer_active(&dum_hcd->timer)) ++ if (!dum_hcd->timer_pending) { ++ dum_hcd->timer_pending = 1; + hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), + HRTIMER_MODE_REL_SOFT); ++ } + + done: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); +@@ -1325,9 +1328,10 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + spin_lock_irqsave(&dum_hcd->dum->lock, flags); + + rc = usb_hcd_check_unlink_urb(hcd, urb, status); +- if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING && +- !list_empty(&dum_hcd->urbp_list)) ++ if (rc == 0 && !dum_hcd->timer_pending) { ++ dum_hcd->timer_pending = 1; + hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); ++ } + + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); + return rc; +@@ -1814,6 +1818,7 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) + + /* look at each urb queued by the host side driver */ + spin_lock_irqsave(&dum->lock, flags); ++ dum_hcd->timer_pending = 0; + + if (!dum_hcd->udev) { + dev_err(dummy_dev(dum_hcd), +@@ -1995,8 +2000,10 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) + if (list_empty(&dum_hcd->urbp_list)) { + usb_put_dev(dum_hcd->udev); + dum_hcd->udev = NULL; +- } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { ++ } else if (!dum_hcd->timer_pending && ++ dum_hcd->rh_state == DUMMY_RH_RUNNING) { + /* want a 1 msec delay here */ ++ dum_hcd->timer_pending = 1; + hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), + HRTIMER_MODE_REL_SOFT); + } +@@ -2391,8 +2398,10 @@ static int dummy_bus_resume(struct usb_hcd *hcd) + } else { + dum_hcd->rh_state = DUMMY_RH_RUNNING; + set_link_state(dum_hcd); +- if (!list_empty(&dum_hcd->urbp_list)) ++ if (!list_empty(&dum_hcd->urbp_list)) { ++ dum_hcd->timer_pending = 1; + hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); ++ } + hcd->state = HC_STATE_RUNNING; + } + spin_unlock_irq(&dum_hcd->dum->lock); +@@ -2523,6 +2532,7 @@ static void dummy_stop(struct usb_hcd *hcd) + struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); + + hrtimer_cancel(&dum_hcd->timer); ++ dum_hcd->timer_pending = 0; + device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs); + dev_info(dummy_dev(dum_hcd), "stopped\n"); + } +-- +2.43.0 + diff --git a/queue-6.1/usb-gadget-dummy_hcd-execute-hrtimer-callback-in-sof.patch b/queue-6.1/usb-gadget-dummy_hcd-execute-hrtimer-callback-in-sof.patch new file mode 100644 index 00000000000..90c7b505de2 --- /dev/null +++ b/queue-6.1/usb-gadget-dummy_hcd-execute-hrtimer-callback-in-sof.patch @@ -0,0 +1,118 @@ +From ea6a80c9cfa890428434f75cdbc8f729c8f34b76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Sep 2024 03:30:51 +0200 +Subject: usb: gadget: dummy_hcd: execute hrtimer callback in softirq context + +From: Andrey Konovalov + +[ Upstream commit 9313d139aa25e572d860f6f673b73a20f32d7f93 ] + +Commit a7f3813e589f ("usb: gadget: dummy_hcd: Switch to hrtimer transfer +scheduler") switched dummy_hcd to use hrtimer and made the timer's +callback be executed in the hardirq context. + +With that change, __usb_hcd_giveback_urb now gets executed in the hardirq +context, which causes problems for KCOV and KMSAN. + +One problem is that KCOV now is unable to collect coverage from +the USB code that gets executed from the dummy_hcd's timer callback, +as KCOV cannot collect coverage in the hardirq context. + +Another problem is that the dummy_hcd hrtimer might get triggered in the +middle of a softirq with KCOV remote coverage collection enabled, and that +causes a WARNING in KCOV, as reported by syzbot. (I sent a separate patch +to shut down this WARNING, but that doesn't fix the other two issues.) + +Finally, KMSAN appears to ignore tracking memory copying operations +that happen in the hardirq context, which causes false positive +kernel-infoleaks, as reported by syzbot. + +Change the hrtimer in dummy_hcd to execute the callback in the softirq +context. + +Reported-by: syzbot+2388cdaeb6b10f0c13ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2388cdaeb6b10f0c13ac +Reported-by: syzbot+17ca2339e34a1d863aad@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=17ca2339e34a1d863aad +Reported-by: syzbot+c793a7eca38803212c61@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=c793a7eca38803212c61 +Reported-by: syzbot+1e6e0b916b211bee1bd6@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=1e6e0b916b211bee1bd6 +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-lkp/202406141323.413a90d2-lkp@intel.com +Fixes: a7f3813e589f ("usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler") +Cc: stable@vger.kernel.org +Acked-by: Marcello Sylvester Bauer +Signed-off-by: Andrey Konovalov +Reported-by: syzbot+edd9fe0d3a65b14588d5@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=edd9fe0d3a65b14588d5 +Link: https://lore.kernel.org/r/20240904013051.4409-1-andrey.konovalov@linux.dev +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/dummy_hcd.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index 32a03de215d37..019e8f3007c94 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -1305,7 +1305,8 @@ static int dummy_urb_enqueue( + + /* kick the scheduler, it'll do the rest */ + if (!hrtimer_active(&dum_hcd->timer)) +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), ++ HRTIMER_MODE_REL_SOFT); + + done: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); +@@ -1326,7 +1327,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING && + !list_empty(&dum_hcd->urbp_list)) +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); + + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); + return rc; +@@ -1996,7 +1997,8 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) + dum_hcd->udev = NULL; + } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { + /* want a 1 msec delay here */ +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), ++ HRTIMER_MODE_REL_SOFT); + } + + spin_unlock_irqrestore(&dum->lock, flags); +@@ -2390,7 +2392,7 @@ static int dummy_bus_resume(struct usb_hcd *hcd) + dum_hcd->rh_state = DUMMY_RH_RUNNING; + set_link_state(dum_hcd); + if (!list_empty(&dum_hcd->urbp_list)) +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); + hcd->state = HC_STATE_RUNNING; + } + spin_unlock_irq(&dum_hcd->dum->lock); +@@ -2468,7 +2470,7 @@ static DEVICE_ATTR_RO(urbs); + + static int dummy_start_ss(struct dummy_hcd *dum_hcd) + { +- hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); + dum_hcd->timer.function = dummy_timer; + dum_hcd->rh_state = DUMMY_RH_RUNNING; + dum_hcd->stream_en_ep = 0; +@@ -2498,7 +2500,7 @@ static int dummy_start(struct usb_hcd *hcd) + return dummy_start_ss(dum_hcd); + + spin_lock_init(&dum_hcd->dum->lock); +- hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); + dum_hcd->timer.function = dummy_timer; + dum_hcd->rh_state = DUMMY_RH_RUNNING; + +-- +2.43.0 + diff --git a/queue-6.1/usb-gadget-dummy_hcd-set-transfer-interval-to-1-micr.patch b/queue-6.1/usb-gadget-dummy_hcd-set-transfer-interval-to-1-micr.patch new file mode 100644 index 00000000000..1df5f0a6e09 --- /dev/null +++ b/queue-6.1/usb-gadget-dummy_hcd-set-transfer-interval-to-1-micr.patch @@ -0,0 +1,60 @@ +From 9d514adef89e7deb2adf6b0fd4b5c8f05b9101c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 17:22:11 +0200 +Subject: usb: gadget: dummy_hcd: Set transfer interval to 1 microframe + +From: Marcello Sylvester Bauer + +[ Upstream commit 0a723ed3baa941ca4f51d87bab00661f41142835 ] + +Currently, the transfer polling interval is set to 1ms, which is the +frame rate of full-speed and low-speed USB. The USB 2.0 specification +introduces microframes (125 microseconds) to improve the timing +precision of data transfers. + +Reducing the transfer interval to 1 microframe increases data throughput +for high-speed and super-speed USB communication + +Signed-off-by: Marcello Sylvester Bauer +Signed-off-by: Marcello Sylvester Bauer +Link: https://lore.kernel.org/r/6295dbb84ca76884551df9eb157cce569377a22c.1712843963.git.sylv@sylv.io +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/dummy_hcd.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index 4f9c6e86456fe..32a03de215d37 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -50,6 +50,8 @@ + #define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */ + #define POWER_BUDGET_3 900 /* in mA */ + ++#define DUMMY_TIMER_INT_NSECS 125000 /* 1 microframe */ ++ + static const char driver_name[] = "dummy_hcd"; + static const char driver_desc[] = "USB Host+Gadget Emulator"; + +@@ -1303,7 +1305,7 @@ static int dummy_urb_enqueue( + + /* kick the scheduler, it'll do the rest */ + if (!hrtimer_active(&dum_hcd->timer)) +- hrtimer_start(&dum_hcd->timer, ms_to_ktime(1), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), HRTIMER_MODE_REL); + + done: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); +@@ -1994,7 +1996,7 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) + dum_hcd->udev = NULL; + } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { + /* want a 1 msec delay here */ +- hrtimer_start(&dum_hcd->timer, ms_to_ktime(1), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), HRTIMER_MODE_REL); + } + + spin_unlock_irqrestore(&dum->lock, flags); +-- +2.43.0 + diff --git a/queue-6.1/usb-gadget-dummy_hcd-switch-to-hrtimer-transfer-sche.patch b/queue-6.1/usb-gadget-dummy_hcd-switch-to-hrtimer-transfer-sche.patch new file mode 100644 index 00000000000..4394781e53a --- /dev/null +++ b/queue-6.1/usb-gadget-dummy_hcd-switch-to-hrtimer-transfer-sche.patch @@ -0,0 +1,153 @@ +From 25489ee7043a92e4d8a17b04ce1f86f22ea047b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 16:51:28 +0200 +Subject: usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler + +From: Marcello Sylvester Bauer + +[ Upstream commit a7f3813e589fd8e2834720829a47b5eb914a9afe ] + +The dummy_hcd transfer scheduler assumes that the internal kernel timer +frequency is set to 1000Hz to give a polling interval of 1ms. Reducing +the timer frequency will result in an anti-proportional reduction in +transfer performance. Switch to a hrtimer to decouple this association. + +Signed-off-by: Marcello Sylvester Bauer +Signed-off-by: Marcello Sylvester Bauer +Reviewed-by: Alan Stern +Link: https://lore.kernel.org/r/57a1c2180ff74661600e010c234d1dbaba1d0d46.1712843963.git.sylv@sylv.io +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/dummy_hcd.c | 35 +++++++++++++++++------------- + 1 file changed, 20 insertions(+), 15 deletions(-) + +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index 899ac9f9c2796..4f9c6e86456fe 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -30,7 +30,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -240,7 +240,7 @@ enum dummy_rh_state { + struct dummy_hcd { + struct dummy *dum; + enum dummy_rh_state rh_state; +- struct timer_list timer; ++ struct hrtimer timer; + u32 port_status; + u32 old_status; + unsigned long re_timeout; +@@ -1302,8 +1302,8 @@ static int dummy_urb_enqueue( + urb->error_count = 1; /* mark as a new urb */ + + /* kick the scheduler, it'll do the rest */ +- if (!timer_pending(&dum_hcd->timer)) +- mod_timer(&dum_hcd->timer, jiffies + 1); ++ if (!hrtimer_active(&dum_hcd->timer)) ++ hrtimer_start(&dum_hcd->timer, ms_to_ktime(1), HRTIMER_MODE_REL); + + done: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); +@@ -1324,7 +1324,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING && + !list_empty(&dum_hcd->urbp_list)) +- mod_timer(&dum_hcd->timer, jiffies); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL); + + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); + return rc; +@@ -1778,7 +1778,7 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb, + * drivers except that the callbacks are invoked from soft interrupt + * context. + */ +-static void dummy_timer(struct timer_list *t) ++static enum hrtimer_restart dummy_timer(struct hrtimer *t) + { + struct dummy_hcd *dum_hcd = from_timer(dum_hcd, t, timer); + struct dummy *dum = dum_hcd->dum; +@@ -1809,8 +1809,6 @@ static void dummy_timer(struct timer_list *t) + break; + } + +- /* FIXME if HZ != 1000 this will probably misbehave ... */ +- + /* look at each urb queued by the host side driver */ + spin_lock_irqsave(&dum->lock, flags); + +@@ -1818,7 +1816,7 @@ static void dummy_timer(struct timer_list *t) + dev_err(dummy_dev(dum_hcd), + "timer fired with no URBs pending?\n"); + spin_unlock_irqrestore(&dum->lock, flags); +- return; ++ return HRTIMER_NORESTART; + } + dum_hcd->next_frame_urbp = NULL; + +@@ -1996,10 +1994,12 @@ static void dummy_timer(struct timer_list *t) + dum_hcd->udev = NULL; + } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { + /* want a 1 msec delay here */ +- mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1)); ++ hrtimer_start(&dum_hcd->timer, ms_to_ktime(1), HRTIMER_MODE_REL); + } + + spin_unlock_irqrestore(&dum->lock, flags); ++ ++ return HRTIMER_NORESTART; + } + + /*-------------------------------------------------------------------------*/ +@@ -2388,7 +2388,7 @@ static int dummy_bus_resume(struct usb_hcd *hcd) + dum_hcd->rh_state = DUMMY_RH_RUNNING; + set_link_state(dum_hcd); + if (!list_empty(&dum_hcd->urbp_list)) +- mod_timer(&dum_hcd->timer, jiffies); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL); + hcd->state = HC_STATE_RUNNING; + } + spin_unlock_irq(&dum_hcd->dum->lock); +@@ -2466,7 +2466,8 @@ static DEVICE_ATTR_RO(urbs); + + static int dummy_start_ss(struct dummy_hcd *dum_hcd) + { +- timer_setup(&dum_hcd->timer, dummy_timer, 0); ++ hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ dum_hcd->timer.function = dummy_timer; + dum_hcd->rh_state = DUMMY_RH_RUNNING; + dum_hcd->stream_en_ep = 0; + INIT_LIST_HEAD(&dum_hcd->urbp_list); +@@ -2495,7 +2496,8 @@ static int dummy_start(struct usb_hcd *hcd) + return dummy_start_ss(dum_hcd); + + spin_lock_init(&dum_hcd->dum->lock); +- timer_setup(&dum_hcd->timer, dummy_timer, 0); ++ hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ dum_hcd->timer.function = dummy_timer; + dum_hcd->rh_state = DUMMY_RH_RUNNING; + + INIT_LIST_HEAD(&dum_hcd->urbp_list); +@@ -2514,8 +2516,11 @@ static int dummy_start(struct usb_hcd *hcd) + + static void dummy_stop(struct usb_hcd *hcd) + { +- device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs); +- dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n"); ++ struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); ++ ++ hrtimer_cancel(&dum_hcd->timer); ++ device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs); ++ dev_info(dummy_dev(dum_hcd), "stopped\n"); + } + + /*-------------------------------------------------------------------------*/ +-- +2.43.0 +