Skip to content

Commit a7f3813

Browse files
sylv-iogregkh
authored andcommitted
usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler
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 <[email protected]> Signed-off-by: Marcello Sylvester Bauer <[email protected]> Reviewed-by: Alan Stern <[email protected]> Link: https://lore.kernel.org/r/57a1c2180ff74661600e010c234d1dbaba1d0d46.1712843963.git.sylv@sylv.io Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 920e752 commit a7f3813

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

drivers/usb/gadget/udc/dummy_hcd.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include <linux/slab.h>
3131
#include <linux/errno.h>
3232
#include <linux/init.h>
33-
#include <linux/timer.h>
33+
#include <linux/hrtimer.h>
3434
#include <linux/list.h>
3535
#include <linux/interrupt.h>
3636
#include <linux/platform_device.h>
@@ -240,7 +240,7 @@ enum dummy_rh_state {
240240
struct dummy_hcd {
241241
struct dummy *dum;
242242
enum dummy_rh_state rh_state;
243-
struct timer_list timer;
243+
struct hrtimer timer;
244244
u32 port_status;
245245
u32 old_status;
246246
unsigned long re_timeout;
@@ -1301,8 +1301,8 @@ static int dummy_urb_enqueue(
13011301
urb->error_count = 1; /* mark as a new urb */
13021302

13031303
/* kick the scheduler, it'll do the rest */
1304-
if (!timer_pending(&dum_hcd->timer))
1305-
mod_timer(&dum_hcd->timer, jiffies + 1);
1304+
if (!hrtimer_active(&dum_hcd->timer))
1305+
hrtimer_start(&dum_hcd->timer, ms_to_ktime(1), HRTIMER_MODE_REL);
13061306

13071307
done:
13081308
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
@@ -1323,7 +1323,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
13231323
rc = usb_hcd_check_unlink_urb(hcd, urb, status);
13241324
if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
13251325
!list_empty(&dum_hcd->urbp_list))
1326-
mod_timer(&dum_hcd->timer, jiffies);
1326+
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL);
13271327

13281328
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
13291329
return rc;
@@ -1777,7 +1777,7 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
17771777
* drivers except that the callbacks are invoked from soft interrupt
17781778
* context.
17791779
*/
1780-
static void dummy_timer(struct timer_list *t)
1780+
static enum hrtimer_restart dummy_timer(struct hrtimer *t)
17811781
{
17821782
struct dummy_hcd *dum_hcd = from_timer(dum_hcd, t, timer);
17831783
struct dummy *dum = dum_hcd->dum;
@@ -1808,16 +1808,14 @@ static void dummy_timer(struct timer_list *t)
18081808
break;
18091809
}
18101810

1811-
/* FIXME if HZ != 1000 this will probably misbehave ... */
1812-
18131811
/* look at each urb queued by the host side driver */
18141812
spin_lock_irqsave(&dum->lock, flags);
18151813

18161814
if (!dum_hcd->udev) {
18171815
dev_err(dummy_dev(dum_hcd),
18181816
"timer fired with no URBs pending?\n");
18191817
spin_unlock_irqrestore(&dum->lock, flags);
1820-
return;
1818+
return HRTIMER_NORESTART;
18211819
}
18221820
dum_hcd->next_frame_urbp = NULL;
18231821

@@ -1995,10 +1993,12 @@ static void dummy_timer(struct timer_list *t)
19951993
dum_hcd->udev = NULL;
19961994
} else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
19971995
/* want a 1 msec delay here */
1998-
mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
1996+
hrtimer_start(&dum_hcd->timer, ms_to_ktime(1), HRTIMER_MODE_REL);
19991997
}
20001998

20011999
spin_unlock_irqrestore(&dum->lock, flags);
2000+
2001+
return HRTIMER_NORESTART;
20022002
}
20032003

20042004
/*-------------------------------------------------------------------------*/
@@ -2387,7 +2387,7 @@ static int dummy_bus_resume(struct usb_hcd *hcd)
23872387
dum_hcd->rh_state = DUMMY_RH_RUNNING;
23882388
set_link_state(dum_hcd);
23892389
if (!list_empty(&dum_hcd->urbp_list))
2390-
mod_timer(&dum_hcd->timer, jiffies);
2390+
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL);
23912391
hcd->state = HC_STATE_RUNNING;
23922392
}
23932393
spin_unlock_irq(&dum_hcd->dum->lock);
@@ -2465,7 +2465,8 @@ static DEVICE_ATTR_RO(urbs);
24652465

24662466
static int dummy_start_ss(struct dummy_hcd *dum_hcd)
24672467
{
2468-
timer_setup(&dum_hcd->timer, dummy_timer, 0);
2468+
hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2469+
dum_hcd->timer.function = dummy_timer;
24692470
dum_hcd->rh_state = DUMMY_RH_RUNNING;
24702471
dum_hcd->stream_en_ep = 0;
24712472
INIT_LIST_HEAD(&dum_hcd->urbp_list);
@@ -2494,7 +2495,8 @@ static int dummy_start(struct usb_hcd *hcd)
24942495
return dummy_start_ss(dum_hcd);
24952496

24962497
spin_lock_init(&dum_hcd->dum->lock);
2497-
timer_setup(&dum_hcd->timer, dummy_timer, 0);
2498+
hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2499+
dum_hcd->timer.function = dummy_timer;
24982500
dum_hcd->rh_state = DUMMY_RH_RUNNING;
24992501

25002502
INIT_LIST_HEAD(&dum_hcd->urbp_list);
@@ -2513,8 +2515,11 @@ static int dummy_start(struct usb_hcd *hcd)
25132515

25142516
static void dummy_stop(struct usb_hcd *hcd)
25152517
{
2516-
device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
2517-
dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
2518+
struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2519+
2520+
hrtimer_cancel(&dum_hcd->timer);
2521+
device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs);
2522+
dev_info(dummy_dev(dum_hcd), "stopped\n");
25182523
}
25192524

25202525
/*-------------------------------------------------------------------------*/

0 commit comments

Comments
 (0)