LKML Archive on lore.kernel.org
 help / Atom feed
* [patch 7/8] genirq/affinity: Defer affinity setting if irq chip is busy
@ 2018-06-04 15:33 Thomas Gleixner
  2018-06-05  7:14 ` Song Liu
  2018-06-06 13:34 ` [tip:x86/urgent] " tip-bot for Thomas Gleixner
  0 siblings, 2 replies; 3+ messages in thread
From: Thomas Gleixner @ 2018-06-04 15:33 UTC (permalink / raw)
  To: LKML
  Cc: Ingo Molnar, Peter Zijlstra, Borislav Petkov, Dmitry Safonov,
	Tariq Toukan, Song Liu, Joerg Roedel, Mike Travis, stable

[-- Attachment #0: genirq-affinity--Defer-affinity-setting-if-irq-chip-is-busy.patch --]
[-- Type: text/plain, Size: 2533 bytes --]

The case that interrupt affinity setting fails with -EBUSY can be handled
in the kernel completely by using the already available generic pending
infrastructure.

If a irq_chip::set_affinity() fails with -EBUSY, handle it like the
interrupts for which irq_chip::set_affinity() can only be invoked from
interrupt context. Copy the new affinity mask to irq_desc::pending_mask and
set the affinity pending bit. The next raised interrupt for the affected
irq will check the pending bit and try to set the new affinity from the
handler. This avoids that -EBUSY is returned when an affinity change is
requested from user space and the previous change has not been cleaned
up. The new affinity will take effect when the next interrupt is raised
from the device.

Fixes: dccfe3147b42 ("x86/vector: Simplify vector move cleanup")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
---
 kernel/irq/manage.c |   37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -204,6 +204,39 @@ int irq_do_set_affinity(struct irq_data
 	return ret;
 }
 
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+static inline int irq_set_affinity_pending(struct irq_data *data,
+					   const struct cpumask *dest)
+{
+	struct irq_desc *desc = irq_data_to_desc(data);
+
+	irqd_set_move_pending(data);
+	irq_copy_pending(desc, dest);
+	return 0;
+}
+#else
+static inline int irq_set_affinity_pending(struct irq_data *data,
+					   const struct cpumask *dest)
+{
+	return -EBUSY;
+}
+#endif
+
+static int irq_try_set_affinity(struct irq_data *data,
+				const struct cpumask *dest, bool force)
+{
+	int ret = irq_do_set_affinity(data, dest, force);
+
+	/*
+	 * In case that the underlying vector management is busy and the
+	 * architecture supports the generic pending mechanism then utilize
+	 * this to avoid returning an error to user space.
+	 */
+	if (ret == -EBUSY && !force)
+		ret = irq_set_affinity_pending(data, dest);
+	return ret;
+}
+
 int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
 			    bool force)
 {
@@ -214,8 +247,8 @@ int irq_set_affinity_locked(struct irq_d
 	if (!chip || !chip->irq_set_affinity)
 		return -EINVAL;
 
-	if (irq_can_move_pcntxt(data)) {
-		ret = irq_do_set_affinity(data, mask, force);
+	if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
+		ret = irq_try_set_affinity(data, mask, force);
 	} else {
 		irqd_set_move_pending(data);
 		irq_copy_pending(desc, mask);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch 7/8] genirq/affinity: Defer affinity setting if irq chip is busy
  2018-06-04 15:33 [patch 7/8] genirq/affinity: Defer affinity setting if irq chip is busy Thomas Gleixner
@ 2018-06-05  7:14 ` Song Liu
  2018-06-06 13:34 ` [tip:x86/urgent] " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 3+ messages in thread
From: Song Liu @ 2018-06-05  7:14 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Ingo Molnar, Peter Zijlstra, Borislav Petkov,
	Dmitry Safonov, Tariq Toukan, Joerg Roedel, Mike Travis, stable

On Mon, Jun 4, 2018 at 8:33 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> The case that interrupt affinity setting fails with -EBUSY can be handled
> in the kernel completely by using the already available generic pending
> infrastructure.
>
> If a irq_chip::set_affinity() fails with -EBUSY, handle it like the
> interrupts for which irq_chip::set_affinity() can only be invoked from
> interrupt context. Copy the new affinity mask to irq_desc::pending_mask and
> set the affinity pending bit. The next raised interrupt for the affected
> irq will check the pending bit and try to set the new affinity from the
> handler. This avoids that -EBUSY is returned when an affinity change is
> requested from user space and the previous change has not been cleaned
> up. The new affinity will take effect when the next interrupt is raised
> from the device.
>
> Fixes: dccfe3147b42 ("x86/vector: Simplify vector move cleanup")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: stable@vger.kernel.org

Tested-by: Song Liu <songliubraving@fb.com>

> ---
>  kernel/irq/manage.c |   37 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 35 insertions(+), 2 deletions(-)
>
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -204,6 +204,39 @@ int irq_do_set_affinity(struct irq_data
>         return ret;
>  }
>
> +#ifdef CONFIG_GENERIC_PENDING_IRQ
> +static inline int irq_set_affinity_pending(struct irq_data *data,
> +                                          const struct cpumask *dest)
> +{
> +       struct irq_desc *desc = irq_data_to_desc(data);
> +
> +       irqd_set_move_pending(data);
> +       irq_copy_pending(desc, dest);
> +       return 0;
> +}
> +#else
> +static inline int irq_set_affinity_pending(struct irq_data *data,
> +                                          const struct cpumask *dest)
> +{
> +       return -EBUSY;
> +}
> +#endif
> +
> +static int irq_try_set_affinity(struct irq_data *data,
> +                               const struct cpumask *dest, bool force)
> +{
> +       int ret = irq_do_set_affinity(data, dest, force);
> +
> +       /*
> +        * In case that the underlying vector management is busy and the
> +        * architecture supports the generic pending mechanism then utilize
> +        * this to avoid returning an error to user space.
> +        */
> +       if (ret == -EBUSY && !force)
> +               ret = irq_set_affinity_pending(data, dest);
> +       return ret;
> +}
> +
>  int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
>                             bool force)
>  {
> @@ -214,8 +247,8 @@ int irq_set_affinity_locked(struct irq_d
>         if (!chip || !chip->irq_set_affinity)
>                 return -EINVAL;
>
> -       if (irq_can_move_pcntxt(data)) {
> -               ret = irq_do_set_affinity(data, mask, force);
> +       if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
> +               ret = irq_try_set_affinity(data, mask, force);
>         } else {
>                 irqd_set_move_pending(data);
>                 irq_copy_pending(desc, mask);
>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:x86/urgent] genirq/affinity: Defer affinity setting if irq chip is busy
  2018-06-04 15:33 [patch 7/8] genirq/affinity: Defer affinity setting if irq chip is busy Thomas Gleixner
  2018-06-05  7:14 ` Song Liu
@ 2018-06-06 13:34 ` " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for Thomas Gleixner @ 2018-06-06 13:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, bp, songliubraving, 0x7f454c46, hpa, jroedel,
	tariqt, mike.travis, tglx, peterz, mingo, liu.song.a23

Commit-ID:  12f47073a40f6aa75119d8f5df4077b7f334cced
Gitweb:     https://git.kernel.org/tip/12f47073a40f6aa75119d8f5df4077b7f334cced
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Mon, 4 Jun 2018 17:33:59 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 6 Jun 2018 15:18:22 +0200

genirq/affinity: Defer affinity setting if irq chip is busy

The case that interrupt affinity setting fails with -EBUSY can be handled
in the kernel completely by using the already available generic pending
infrastructure.

If a irq_chip::set_affinity() fails with -EBUSY, handle it like the
interrupts for which irq_chip::set_affinity() can only be invoked from
interrupt context. Copy the new affinity mask to irq_desc::pending_mask and
set the affinity pending bit. The next raised interrupt for the affected
irq will check the pending bit and try to set the new affinity from the
handler. This avoids that -EBUSY is returned when an affinity change is
requested from user space and the previous change has not been cleaned
up. The new affinity will take effect when the next interrupt is raised
from the device.

Fixes: dccfe3147b42 ("x86/vector: Simplify vector move cleanup")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Song Liu <songliubraving@fb.com>
Cc: Joerg Roedel <jroedel@suse.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <liu.song.a23@gmail.com>
Cc: Dmitry Safonov <0x7f454c46@gmail.com>
Cc: stable@vger.kernel.org
Cc: Mike Travis <mike.travis@hpe.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Tariq Toukan <tariqt@mellanox.com>
Link: https://lkml.kernel.org/r/20180604162224.819273597@linutronix.de

---
 kernel/irq/manage.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index e3336d904f64..facfecfc543c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -204,6 +204,39 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	return ret;
 }
 
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+static inline int irq_set_affinity_pending(struct irq_data *data,
+					   const struct cpumask *dest)
+{
+	struct irq_desc *desc = irq_data_to_desc(data);
+
+	irqd_set_move_pending(data);
+	irq_copy_pending(desc, dest);
+	return 0;
+}
+#else
+static inline int irq_set_affinity_pending(struct irq_data *data,
+					   const struct cpumask *dest)
+{
+	return -EBUSY;
+}
+#endif
+
+static int irq_try_set_affinity(struct irq_data *data,
+				const struct cpumask *dest, bool force)
+{
+	int ret = irq_do_set_affinity(data, dest, force);
+
+	/*
+	 * In case that the underlying vector management is busy and the
+	 * architecture supports the generic pending mechanism then utilize
+	 * this to avoid returning an error to user space.
+	 */
+	if (ret == -EBUSY && !force)
+		ret = irq_set_affinity_pending(data, dest);
+	return ret;
+}
+
 int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
 			    bool force)
 {
@@ -214,8 +247,8 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
 	if (!chip || !chip->irq_set_affinity)
 		return -EINVAL;
 
-	if (irq_can_move_pcntxt(data)) {
-		ret = irq_do_set_affinity(data, mask, force);
+	if (irq_can_move_pcntxt(data) && !irqd_is_setaffinity_pending(data)) {
+		ret = irq_try_set_affinity(data, mask, force);
 	} else {
 		irqd_set_move_pending(data);
 		irq_copy_pending(desc, mask);

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, back to index

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-04 15:33 [patch 7/8] genirq/affinity: Defer affinity setting if irq chip is busy Thomas Gleixner
2018-06-05  7:14 ` Song Liu
2018-06-06 13:34 ` [tip:x86/urgent] " tip-bot for Thomas Gleixner

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org linux-kernel@archiver.kernel.org
	public-inbox-index lkml


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox