From 460b15df7d633faacc39f76a2f9f2b5da92d89eb Mon Sep 17 00:00:00 2001
From: Daniel J Blueman <daniel@numascale.com>
Date: Mon, 4 Jul 2016 14:40:17 +0800
Subject: [PATCH] Reject off-node interrupt affinity

Signed-off-by: Daniel J Blueman <daniel@numascale.com>
---
 kernel/irq/manage.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index cc1cc64..db94cb1 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -230,10 +230,27 @@ int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force)
 	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
 	int ret;
+	const struct cpumask *node;
+	cpumask_var_t mask2;
 
 	if (!desc)
 		return -EINVAL;
 
+	/* Reject affinity if off-node */
+	node = cpumask_of_node(irq_desc_get_node(desc));
+	if (!alloc_cpumask_var(&mask2, GFP_KERNEL))
+		return -ENOMEM;
+
+	/* Workaround: mask out upper bits */
+	cpumask_and(mask2, mask, cpu_online_mask);
+	ret = cpumask_subset(mask2, node);
+	free_cpumask_var(mask2);
+
+	if (!ret) {
+		pr_crit("Attempt to set interrupt %u affinity off-node; disable irqbalance or report to report to support@numascale.com\n", irq);
+		return -EINVAL;
+	}
+
 	raw_spin_lock_irqsave(&desc->lock, flags);
 	ret = irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force);
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
-- 
2.7.4

