action->flags |= __irq_ino(irq) << 48;
#define get_ino_in_irqaction(action) (action->flags >> 48)
+#if NR_CPUS > 64
+#error irqaction embedded smp affinity does not work with > 64 cpus, FIXME
+#endif
+
#define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff)
#define get_smpaff_in_irqaction(action) ((action)->mask)
action->next = NULL;
action->dev_id = dev_id;
put_ino_in_irqaction(action, irq);
- put_smpaff_in_irqaction(action, CPU_MASK_NONE);
+ put_smpaff_in_irqaction(action, 0);
if (tmp)
tmp->next = action;
* Just Do It.
*/
struct irqaction *ap = bp->irq_info;
- cpumask_t cpu_mask;
+ cpumask_t cpu_mask = get_smpaff_in_irqaction(ap);
unsigned int buddy, ticks;
- cpu_mask = get_smpaff_in_irqaction(ap);
cpus_and(cpu_mask, cpu_mask, cpu_online_map);
if (cpus_empty(cpu_mask))
cpu_mask = cpu_online_map;
if (++buddy >= NR_CPUS)
buddy = 0;
if (++ticks > NR_CPUS) {
- put_smpaff_in_irqaction(ap, CPU_MASK_NONE);
+ put_smpaff_in_irqaction(ap, 0);
goto out;
}
}
action->name = name;
action->next = NULL;
put_ino_in_irqaction(action, irq);
- put_smpaff_in_irqaction(action, CPU_MASK_NONE);
+ put_smpaff_in_irqaction(action, 0);
*(bucket->pil + irq_action) = action;
enable_irq(irq);
#ifdef CONFIG_SMP
+#define HEX_DIGITS 16
+
+static unsigned int parse_hex_value (const char __user *buffer,
+ unsigned long count, unsigned long *ret)
+{
+ unsigned char hexnum [HEX_DIGITS];
+ unsigned long value;
+ int i;
+
+ if (!count)
+ return -EINVAL;
+ if (count > HEX_DIGITS)
+ count = HEX_DIGITS;
+ if (copy_from_user(hexnum, buffer, count))
+ return -EFAULT;
+
+ /*
+ * Parse the first 8 characters as a hex string, any non-hex char
+ * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
+ */
+ value = 0;
+
+ for (i = 0; i < count; i++) {
+ unsigned int c = hexnum[i];
+
+ switch (c) {
+ case '0' ... '9': c -= '0'; break;
+ case 'a' ... 'f': c -= 'a'-10; break;
+ case 'A' ... 'F': c -= 'A'-10; break;
+ default:
+ goto out;
+ }
+ value = (value << 4) | c;
+ }
+out:
+ *ret = value;
+ return 0;
+}
+
static int irq_affinity_read_proc (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct ino_bucket *bp = ivector_table + (long)data;
struct irqaction *ap = bp->irq_info;
- cpumask_t mask;
+ cpumask_t mask = get_smpaff_in_irqaction(ap);
int len;
- mask = get_smpaff_in_irqaction(ap);
if (cpus_empty(mask))
mask = cpu_online_map;
return len;
}
-static inline void set_intr_affinity(int irq, cpumask_t hw_aff)
+static inline void set_intr_affinity(int irq, unsigned long hw_aff)
{
struct ino_bucket *bp = ivector_table + irq;
unsigned long count, void *data)
{
int irq = (long) data, full_count = count, err;
- cpumask_t new_value;
+ unsigned long new_value, i;
- err = cpumask_parse(buffer, count, new_value);
+ err = parse_hex_value(buffer, count, &new_value);
/*
* Do not allow disabling IRQs completely - it's a too easy
* way to make the system unusable accidentally :-) At least
* one online CPU still has to be targeted.
*/
- cpus_and(new_value, new_value, cpu_online_map);
- if (cpus_empty(new_value))
+ for (i = 0; i < NR_CPUS; i++) {
+ if ((new_value & (1UL << i)) != 0 &&
+ !cpu_online(i))
+ new_value &= ~(1UL << i);
+ }
+
+ if (!new_value)
return -EINVAL;
set_intr_affinity(irq, new_value);
void init_irq_proc (void)
{
/* create /proc/irq */
- root_irq_dir = proc_mkdir("irq", NULL);
+ root_irq_dir = proc_mkdir("irq", 0);
}