[PATCH net-next 5/6] eventpoll: Control irq suspension for prefer_busy_poll

From: Joe Damato
Date: Fri Aug 23 2024 - 13:33:29 EST


From: Martin Karsten <mkarsten@xxxxxxxxxxxx>

When events are reported to userland and prefer_busy_poll is set, irqs are
temporarily suspended using napi_suspend_irqs.

If no events are found and ep_poll would go to sleep, irq suspension is
cancelled using napi_resume_irqs.

Signed-off-by: Martin Karsten <mkarsten@xxxxxxxxxxxx>
Co-developed-by: Joe Damato <jdamato@xxxxxxxxxx>
Signed-off-by: Joe Damato <jdamato@xxxxxxxxxx>
Tested-by: Joe Damato <jdamato@xxxxxxxxxx>
Tested-by: Martin Karsten <mkarsten@xxxxxxxxxxxx>
---
rfc -> v1:
- move irq resume code from ep_free to a helper which either resumes
IRQs or does nothing if !defined(CONFIG_NET_RX_BUSY_POLL).

fs/eventpoll.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index cc47f72005ed..5dbe717c06b4 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -457,6 +457,8 @@ static bool ep_busy_loop(struct eventpoll *ep, int nonblock)
* it back in when we have moved a socket with a valid NAPI
* ID onto the ready list.
*/
+ if (prefer_busy_poll)
+ napi_resume_irqs(napi_id);
ep->napi_id = 0;
return false;
}
@@ -540,6 +542,22 @@ static long ep_eventpoll_bp_ioctl(struct file *file, unsigned int cmd,
}
}

+static void ep_suspend_napi_irqs(struct eventpoll *ep)
+{
+ unsigned int napi_id = READ_ONCE(ep->napi_id);
+
+ if (napi_id >= MIN_NAPI_ID && READ_ONCE(ep->prefer_busy_poll))
+ napi_suspend_irqs(napi_id);
+}
+
+static void ep_resume_napi_irqs(struct eventpoll *ep)
+{
+ unsigned int napi_id = READ_ONCE(ep->napi_id);
+
+ if (napi_id >= MIN_NAPI_ID && READ_ONCE(ep->prefer_busy_poll))
+ napi_resume_irqs(napi_id);
+}
+
#else

static inline bool ep_busy_loop(struct eventpoll *ep, int nonblock)
@@ -557,6 +575,13 @@ static long ep_eventpoll_bp_ioctl(struct file *file, unsigned int cmd,
return -EOPNOTSUPP;
}

+static void ep_suspend_napi_irqs(struct eventpoll *ep)
+{
+}
+
+static void ep_resume_napi_irqs(struct eventpoll *ep)
+{
+}
#endif /* CONFIG_NET_RX_BUSY_POLL */

/*
@@ -788,6 +813,7 @@ static bool ep_refcount_dec_and_test(struct eventpoll *ep)

static void ep_free(struct eventpoll *ep)
{
+ ep_resume_napi_irqs(ep);
mutex_destroy(&ep->mtx);
free_uid(ep->user);
wakeup_source_unregister(ep->ws);
@@ -2005,8 +2031,10 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
* trying again in search of more luck.
*/
res = ep_send_events(ep, events, maxevents);
- if (res)
+ if (res) {
+ ep_suspend_napi_irqs(ep);
return res;
+ }
}

if (timed_out)
--
2.25.1