mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>,
	linux-kernel@vger.kernel.org
Subject: [PATCH] RFC: genirq: allow userspace to set default priority of irq threads
Date: Thu, 16 May 2019 16:49:37 +0200	[thread overview]
Message-ID: <20190516144937.20101-1-linux@rasmusvillemoes.dk> (raw)

On -rt kernels, it is sometimes desirable to be able to prioritize
some hardware interrupts over others, i.e. being able to set the
priorities of the irq threads different from the default of 50. While
chrt(1) can be used after the threads are created, there are at least
two problems with that: (1) threads are created and destroyed as
devices are brought up and down, making it necessary to continuously
monitor /proc for new irq threads, leading to (2) a device may run for
a while with its irq thread(s) at the wrong priority.

This is just a quick POC to start some discussion. Probably the
locking is all wrong. But this at least gives userspace a way
of assigning a priority to a specific hardware interrupt by
matching on the chip_name and hwirq - unfortunately, chip_name is not
necessarily unique, so it doesn't work for all cases.

This would probably be a better fit in /proc alongside the affinity
settings, but the problem with that is that the /proc entries don't
exist until __setup_irq() is called the first time. [Btw, why are
the sysfs files dependent on CONFIG_SPARSE_IRQ?]

Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
 include/linux/irqdesc.h |  2 ++
 kernel/irq/irqdesc.c    | 57 +++++++++++++++++++++++++++++++++++++++++
 kernel/irq/manage.c     | 11 ++++----
 3 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index d6e2ab538ef2..29cf7ff99cf3 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -5,6 +5,7 @@
 #include <linux/rcupdate.h>
 #include <linux/kobject.h>
 #include <linux/mutex.h>
+#include <uapi/linux/sched/types.h>
 
 /*
  * Core internal functions to deal with irq descriptors
@@ -106,6 +107,7 @@ struct irq_desc {
 	int			parent_irq;
 	struct module		*owner;
 	const char		*name;
+	struct sched_param	sched_param;
 } ____cacheline_internodealigned_in_smp;
 
 #ifdef CONFIG_SPARSE_IRQ
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index c52b737ab8e3..42f72bf6f046 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -125,6 +125,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
 	for_each_possible_cpu(cpu)
 		*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
 	desc_smp_init(desc, node, affinity);
+	desc->sched_param.sched_priority = MAX_USER_RT_PRIO/2;
 }
 
 int nr_irqs = NR_IRQS;
@@ -143,6 +144,9 @@ static struct kobject *irq_kobj_base;
 #define IRQ_ATTR_RO(_name) \
 static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
 
+#define IRQ_ATTR_RW(_name) \
+static struct kobj_attribute _name##_attr = __ATTR_RW(_name)
+
 static ssize_t per_cpu_count_show(struct kobject *kobj,
 				  struct kobj_attribute *attr, char *buf)
 {
@@ -265,6 +269,58 @@ static ssize_t actions_show(struct kobject *kobj,
 }
 IRQ_ATTR_RO(actions);
 
+static ssize_t prio_show(struct kobject *kobj,
+			 struct kobj_attribute *attr, char *buf)
+{
+	struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
+	int prio;
+
+	mutex_lock(&desc->request_mutex);
+	prio = desc->sched_param.sched_priority;
+	mutex_unlock(&desc->request_mutex);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", prio);
+}
+
+static ssize_t prio_store(struct kobject *kobj, struct kobj_attribute *attr,
+			  const char *buf, size_t n)
+{
+	struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
+	struct task_struct *thread;
+	struct irqaction *action;
+	ssize_t ret;
+	int prio;
+
+	ret = kstrtoint(buf, 10, &prio);
+	if (ret)
+		return ret;
+	if (prio < 1 || prio > MAX_USER_RT_PRIO - 1)
+		return -ERANGE;
+
+	mutex_lock(&desc->request_mutex);
+
+	desc->sched_param.sched_priority = prio;
+	for (action = desc->action; action; action = action->next) {
+		struct sched_param sp = desc->sched_param;
+
+		thread = action->thread;
+		if (thread)
+			sched_setscheduler_nocheck(thread, SCHED_FIFO, &sp);
+		if (action->secondary) {
+			thread = action->secondary->thread;
+			if (thread) {
+				sp.sched_priority -= 1;
+				sched_setscheduler_nocheck(thread, SCHED_FIFO, &sp);
+			}
+		}
+	}
+
+	mutex_unlock(&desc->request_mutex);
+
+	return n;
+}
+IRQ_ATTR_RW(prio);
+
 static struct attribute *irq_attrs[] = {
 	&per_cpu_count_attr.attr,
 	&chip_name_attr.attr,
@@ -273,6 +329,7 @@ static struct attribute *irq_attrs[] = {
 	&wakeup_attr.attr,
 	&name_attr.attr,
 	&actions_attr.attr,
+	&prio_attr.attr,
 	NULL
 };
 ATTRIBUTE_GROUPS(irq);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 78f3ddeb7fe4..a915c5128211 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1203,12 +1203,11 @@ static void irq_nmi_teardown(struct irq_desc *desc)
 }
 
 static int
-setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
+setup_irq_thread(struct irqaction *new, struct irq_desc *desc, bool secondary)
 {
+	struct sched_param param = desc->sched_param;
+	unsigned int irq = irq_desc_get_irq(desc);
 	struct task_struct *t;
-	struct sched_param param = {
-		.sched_priority = MAX_USER_RT_PRIO/2,
-	};
 
 	if (!secondary) {
 		t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
@@ -1312,11 +1311,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 	 * thread.
 	 */
 	if (new->thread_fn && !nested) {
-		ret = setup_irq_thread(new, irq, false);
+		ret = setup_irq_thread(new, desc, false);
 		if (ret)
 			goto out_mput;
 		if (new->secondary) {
-			ret = setup_irq_thread(new->secondary, irq, true);
+			ret = setup_irq_thread(new->secondary, desc, true);
 			if (ret)
 				goto out_thread;
 		}
-- 
2.20.1


                 reply	other threads:[~2019-05-16 14:49 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20190516144937.20101-1-linux@rasmusvillemoes.dk \
    --to=linux@rasmusvillemoes.dk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /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®