From: Marcello Sylvester Bauer <email>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Marcello Sylvester Bauer" <sylv@sylv.io>,
"Marcello Sylvester Bauer" <marcello.bauer@9elements.com>,
"Matthias Stöckl" <matthias.stoeckl@secunet.com>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v1 1/2] usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler
Date: Thu, 11 Apr 2024 16:51:28 +0200 [thread overview]
Message-ID: <57a1c2180ff74661600e010c234d1dbaba1d0d46.1712843963.git.sylv@sylv.io> (raw)
In-Reply-To: <cover.1712843963.git.sylv@sylv.io>
From: Marcello Sylvester Bauer <sylv@sylv.io>
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 <marcello.bauer@9elements.com>
Signed-off-by: Marcello Sylvester Bauer <sylv@sylv.io>
---
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 0953e1b5c030..dab559d8ee8c 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
@@ -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;
@@ -1301,8 +1301,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);
@@ -1323,7 +1323,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;
@@ -1777,7 +1777,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;
@@ -1808,8 +1808,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);
@@ -1817,7 +1815,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;
@@ -1995,10 +1993,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;
}
/*-------------------------------------------------------------------------*/
@@ -2387,7 +2387,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);
@@ -2465,7 +2465,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);
@@ -2494,7 +2495,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);
@@ -2513,8 +2515,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.44.0
WARNING: multiple messages have this Message-ID
From: Marcello Sylvester Bauer <sylv@sylv.io>
To: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Marcello Sylvester Bauer <marcello.bauer@9elements.com>,
Matthias Stoeckl <matthias.stoeckl@secunet.com>,
Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>,
Marcello Sylvester Bauer <sylv@sylv.io>
Subject: [PATCH v1 1/2] usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler
Date: Thu, 11 Apr 2024 17:22:10 +0200 [thread overview]
Message-ID: <57a1c2180ff74661600e010c234d1dbaba1d0d46.1712843963.git.sylv@sylv.io> (raw)
Message-ID: <20240411152210.zJj03LGtB0nqclR-hl2oCV3NN_RSek86oZ_Op4d-tNU@z> (raw)
In-Reply-To: <cover.1712843963.git.sylv@sylv.io>
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 <marcello.bauer@9elements.com>
Signed-off-by: Marcello Sylvester Bauer <sylv@sylv.io>
---
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 0953e1b5c030..dab559d8ee8c 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
@@ -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;
@@ -1301,8 +1301,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);
@@ -1323,7 +1323,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;
@@ -1777,7 +1777,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;
@@ -1808,8 +1808,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);
@@ -1817,7 +1815,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;
@@ -1995,10 +1993,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;
}
/*-------------------------------------------------------------------------*/
@@ -2387,7 +2387,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);
@@ -2465,7 +2465,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);
@@ -2494,7 +2495,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);
@@ -2513,8 +2515,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.44.0
next prev parent reply other threads:[~2024-04-11 15:01 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-11 15:22 [PATCH v1 0/2] usb: gadget: dummy_hcd: Switch to hrtimers for better performance Marcello Sylvester Bauer
2024-04-11 14:51 ` Marcello Sylvester Bauer [this message]
2024-04-11 15:22 ` [PATCH v1 1/2] usb: gadget: dummy_hcd: Switch to hrtimer transfer scheduler Marcello Sylvester Bauer
2024-04-11 16:30 ` Alan Stern
2024-04-11 14:51 ` [PATCH v1 2/2] usb: gadget: dummy_hcd: Set transfer interval to 1 microframe Marcello Sylvester Bauer
2024-04-11 15:22 ` Marcello Sylvester Bauer
2024-04-11 16:21 ` Alan Stern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=57a1c2180ff74661600e010c234d1dbaba1d0d46.1712843963.git.sylv@sylv.io \
--to=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=marcello.bauer@9elements.com \
--cc=matthias.stoeckl@secunet.com \
--cc=sylv@sylv.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®