aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>2010-04-30 17:44:50 -0400
committerThomas Gleixner <tglx@linutronix.de>2010-05-03 05:50:57 -0400
commite7a297b0d7d6049bd4e423ac1e17da31e4c401b8 (patch)
treef10f12806a637b09bec89ef5428d981c4c1a4bc9 /kernel
parent6932bf37bed45ce8ed531928b1b0f98162fe6df6 (diff)
genirq: Add CPU mask affinity hint
This patch adds a cpumask affinity hint to the irq_desc structure, along with a registration function and a read-only proc entry for each interrupt. This affinity_hint handle for each interrupt can be used by underlying drivers that need a better mechanism to control interrupt affinity. The underlying driver can register a cpumask for the interrupt, which will allow the driver to provide the CPU mask for the interrupt to anything that requests it. The intent is to extend the userspace daemon, irqbalance, to help hint to it a preferred CPU mask to balance the interrupt into. [ tglx: Fixed compile warnings, added WARN_ON, made SMP only ] Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Cc: davem@davemloft.net Cc: arjan@linux.jf.intel.com Cc: bhutchings@solarflare.com LKML-Reference: <20100430214445.3992.41647.stgit@ppwaskie-hc2.jf.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/irq/manage.c22
-rw-r--r--kernel/irq/proc.c39
2 files changed, 61 insertions, 0 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 444d5a81a209..3164ba7ce151 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -138,6 +138,22 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
138 return 0; 138 return 0;
139} 139}
140 140
141int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
142{
143 struct irq_desc *desc = irq_to_desc(irq);
144 unsigned long flags;
145
146 if (!desc)
147 return -EINVAL;
148
149 raw_spin_lock_irqsave(&desc->lock, flags);
150 desc->affinity_hint = m;
151 raw_spin_unlock_irqrestore(&desc->lock, flags);
152
153 return 0;
154}
155EXPORT_SYMBOL_GPL(irq_set_affinity_hint);
156
141#ifndef CONFIG_AUTO_IRQ_AFFINITY 157#ifndef CONFIG_AUTO_IRQ_AFFINITY
142/* 158/*
143 * Generic version of the affinity autoselector. 159 * Generic version of the affinity autoselector.
@@ -906,6 +922,12 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
906 desc->chip->disable(irq); 922 desc->chip->disable(irq);
907 } 923 }
908 924
925#ifdef CONFIG_SMP
926 /* make sure affinity_hint is cleaned up */
927 if (WARN_ON_ONCE(desc->affinity_hint))
928 desc->affinity_hint = NULL;
929#endif
930
909 raw_spin_unlock_irqrestore(&desc->lock, flags); 931 raw_spin_unlock_irqrestore(&desc->lock, flags);
910 932
911 unregister_handler_proc(irq, action); 933 unregister_handler_proc(irq, action);
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index fe92dc5190dd..4f9427a30e14 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -32,6 +32,29 @@ static int irq_affinity_proc_show(struct seq_file *m, void *v)
32 return 0; 32 return 0;
33} 33}
34 34
35static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
36{
37 struct irq_desc *desc = irq_to_desc((long)m->private);
38 unsigned long flags;
39 cpumask_var_t mask;
40
41 if (!alloc_cpumask_var(&mask, GFP_KERNEL))
42 return -ENOMEM;
43
44 raw_spin_lock_irqsave(&desc->lock, flags);
45 if (desc->affinity_hint)
46 cpumask_copy(mask, desc->affinity_hint);
47 else
48 cpumask_setall(mask);
49 raw_spin_unlock_irqrestore(&desc->lock, flags);
50
51 seq_cpumask(m, mask);
52 seq_putc(m, '\n');
53 free_cpumask_var(mask);
54
55 return 0;
56}
57
35#ifndef is_affinity_mask_valid 58#ifndef is_affinity_mask_valid
36#define is_affinity_mask_valid(val) 1 59#define is_affinity_mask_valid(val) 1
37#endif 60#endif
@@ -84,6 +107,11 @@ static int irq_affinity_proc_open(struct inode *inode, struct file *file)
84 return single_open(file, irq_affinity_proc_show, PDE(inode)->data); 107 return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
85} 108}
86 109
110static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
111{
112 return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data);
113}
114
87static const struct file_operations irq_affinity_proc_fops = { 115static const struct file_operations irq_affinity_proc_fops = {
88 .open = irq_affinity_proc_open, 116 .open = irq_affinity_proc_open,
89 .read = seq_read, 117 .read = seq_read,
@@ -92,6 +120,13 @@ static const struct file_operations irq_affinity_proc_fops = {
92 .write = irq_affinity_proc_write, 120 .write = irq_affinity_proc_write,
93}; 121};
94 122
123static const struct file_operations irq_affinity_hint_proc_fops = {
124 .open = irq_affinity_hint_proc_open,
125 .read = seq_read,
126 .llseek = seq_lseek,
127 .release = single_release,
128};
129
95static int default_affinity_show(struct seq_file *m, void *v) 130static int default_affinity_show(struct seq_file *m, void *v)
96{ 131{
97 seq_cpumask(m, irq_default_affinity); 132 seq_cpumask(m, irq_default_affinity);
@@ -252,6 +287,10 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
252 proc_create_data("smp_affinity", 0600, desc->dir, 287 proc_create_data("smp_affinity", 0600, desc->dir,
253 &irq_affinity_proc_fops, (void *)(long)irq); 288 &irq_affinity_proc_fops, (void *)(long)irq);
254 289
290 /* create /proc/irq/<irq>/affinity_hint */
291 proc_create_data("affinity_hint", 0400, desc->dir,
292 &irq_affinity_hint_proc_fops, (void *)(long)irq);
293
255 proc_create_data("node", 0444, desc->dir, 294 proc_create_data("node", 0444, desc->dir,
256 &irq_node_proc_fops, (void *)(long)irq); 295 &irq_node_proc_fops, (void *)(long)irq);
257#endif 296#endif