linux/kernel/irq/proc.c
<<
>>
Prefs
   1/*
   2 * linux/kernel/irq/proc.c
   3 *
   4 * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
   5 *
   6 * This file contains the /proc/irq/ handling code.
   7 */
   8
   9#include <linux/irq.h>
  10#include <linux/proc_fs.h>
  11#include <linux/seq_file.h>
  12#include <linux/interrupt.h>
  13
  14#include "internals.h"
  15
  16static struct proc_dir_entry *root_irq_dir;
  17
  18#ifdef CONFIG_SMP
  19
  20static int irq_affinity_proc_show(struct seq_file *m, void *v)
  21{
  22        struct irq_desc *desc = irq_to_desc((long)m->private);
  23        cpumask_t *mask = &desc->affinity;
  24
  25#ifdef CONFIG_GENERIC_PENDING_IRQ
  26        if (desc->status & IRQ_MOVE_PENDING)
  27                mask = &desc->pending_mask;
  28#endif
  29        seq_cpumask(m, mask);
  30        seq_putc(m, '\n');
  31        return 0;
  32}
  33
  34#ifndef is_affinity_mask_valid
  35#define is_affinity_mask_valid(val) 1
  36#endif
  37
  38int no_irq_affinity;
  39static ssize_t irq_affinity_proc_write(struct file *file,
  40                const char __user *buffer, size_t count, loff_t *pos)
  41{
  42        unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data;
  43        cpumask_t new_value;
  44        int err;
  45
  46        if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity ||
  47            irq_balancing_disabled(irq))
  48                return -EIO;
  49
  50        err = cpumask_parse_user(buffer, count, new_value);
  51        if (err)
  52                return err;
  53
  54        if (!is_affinity_mask_valid(new_value))
  55                return -EINVAL;
  56
  57        /*
  58         * Do not allow disabling IRQs completely - it's a too easy
  59         * way to make the system unusable accidentally :-) At least
  60         * one online CPU still has to be targeted.
  61         */
  62        if (!cpus_intersects(new_value, cpu_online_map))
  63                /* Special case for empty set - allow the architecture
  64                   code to set default SMP affinity. */
  65                return irq_select_affinity_usr(irq) ? -EINVAL : count;
  66
  67        irq_set_affinity(irq, new_value);
  68
  69        return count;
  70}
  71
  72static int irq_affinity_proc_open(struct inode *inode, struct file *file)
  73{
  74        return single_open(file, irq_affinity_proc_show, PDE(inode)->data);
  75}
  76
  77static const struct file_operations irq_affinity_proc_fops = {
  78        .open           = irq_affinity_proc_open,
  79        .read           = seq_read,
  80        .llseek         = seq_lseek,
  81        .release        = single_release,
  82        .write          = irq_affinity_proc_write,
  83};
  84
  85static int default_affinity_show(struct seq_file *m, void *v)
  86{
  87        seq_cpumask(m, &irq_default_affinity);
  88        seq_putc(m, '\n');
  89        return 0;
  90}
  91
  92static ssize_t default_affinity_write(struct file *file,
  93                const char __user *buffer, size_t count, loff_t *ppos)
  94{
  95        cpumask_t new_value;
  96        int err;
  97
  98        err = cpumask_parse_user(buffer, count, new_value);
  99        if (err)
 100                return err;
 101
 102        if (!is_affinity_mask_valid(new_value))
 103                return -EINVAL;
 104
 105        /*
 106         * Do not allow disabling IRQs completely - it's a too easy
 107         * way to make the system unusable accidentally :-) At least
 108         * one online CPU still has to be targeted.
 109         */
 110        if (!cpus_intersects(new_value, cpu_online_map))
 111                return -EINVAL;
 112
 113        irq_default_affinity = new_value;
 114
 115        return count;
 116}
 117
 118static int default_affinity_open(struct inode *inode, struct file *file)
 119{
 120        return single_open(file, default_affinity_show, NULL);
 121}
 122
 123static const struct file_operations default_affinity_proc_fops = {
 124        .open           = default_affinity_open,
 125        .read           = seq_read,
 126        .llseek         = seq_lseek,
 127        .release        = single_release,
 128        .write          = default_affinity_write,
 129};
 130#endif
 131
 132static int irq_spurious_read(char *page, char **start, off_t off,
 133                                  int count, int *eof, void *data)
 134{
 135        struct irq_desc *desc = irq_to_desc((long) data);
 136        return sprintf(page, "count %u\n"
 137                             "unhandled %u\n"
 138                             "last_unhandled %u ms\n",
 139                        desc->irq_count,
 140                        desc->irqs_unhandled,
 141                        jiffies_to_msecs(desc->last_unhandled));
 142}
 143
 144#define MAX_NAMELEN 128
 145
 146static int name_unique(unsigned int irq, struct irqaction *new_action)
 147{
 148        struct irq_desc *desc = irq_to_desc(irq);
 149        struct irqaction *action;
 150        unsigned long flags;
 151        int ret = 1;
 152
 153        spin_lock_irqsave(&desc->lock, flags);
 154        for (action = desc->action ; action; action = action->next) {
 155                if ((action != new_action) && action->name &&
 156                                !strcmp(new_action->name, action->name)) {
 157                        ret = 0;
 158                        break;
 159                }
 160        }
 161        spin_unlock_irqrestore(&desc->lock, flags);
 162        return ret;
 163}
 164
 165void register_handler_proc(unsigned int irq, struct irqaction *action)
 166{
 167        char name [MAX_NAMELEN];
 168        struct irq_desc *desc = irq_to_desc(irq);
 169
 170        if (!desc->dir || action->dir || !action->name ||
 171                                        !name_unique(irq, action))
 172                return;
 173
 174        memset(name, 0, MAX_NAMELEN);
 175        snprintf(name, MAX_NAMELEN, "%s", action->name);
 176
 177        /* create /proc/irq/1234/handler/ */
 178        action->dir = proc_mkdir(name, desc->dir);
 179}
 180
 181#undef MAX_NAMELEN
 182
 183#define MAX_NAMELEN 10
 184
 185void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 186{
 187        char name [MAX_NAMELEN];
 188        struct proc_dir_entry *entry;
 189
 190        if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir)
 191                return;
 192
 193        memset(name, 0, MAX_NAMELEN);
 194        sprintf(name, "%d", irq);
 195
 196        /* create /proc/irq/1234 */
 197        desc->dir = proc_mkdir(name, root_irq_dir);
 198
 199#ifdef CONFIG_SMP
 200        /* create /proc/irq/<irq>/smp_affinity */
 201        proc_create_data("smp_affinity", 0600, desc->dir,
 202                         &irq_affinity_proc_fops, (void *)(long)irq);
 203#endif
 204
 205        entry = create_proc_entry("spurious", 0444, desc->dir);
 206        if (entry) {
 207                entry->data = (void *)(long)irq;
 208                entry->read_proc = irq_spurious_read;
 209        }
 210}
 211
 212#undef MAX_NAMELEN
 213
 214void unregister_handler_proc(unsigned int irq, struct irqaction *action)
 215{
 216        if (action->dir) {
 217                struct irq_desc *desc = irq_to_desc(irq);
 218
 219                remove_proc_entry(action->dir->name, desc->dir);
 220        }
 221}
 222
 223static void register_default_affinity_proc(void)
 224{
 225#ifdef CONFIG_SMP
 226        proc_create("irq/default_smp_affinity", 0600, NULL,
 227                    &default_affinity_proc_fops);
 228#endif
 229}
 230
 231void init_irq_proc(void)
 232{
 233        unsigned int irq;
 234        struct irq_desc *desc;
 235
 236        /* create /proc/irq */
 237        root_irq_dir = proc_mkdir("irq", NULL);
 238        if (!root_irq_dir)
 239                return;
 240
 241        register_default_affinity_proc();
 242
 243        /*
 244         * Create entries for all existing IRQs.
 245         */
 246        for_each_irq_desc(irq, desc)
 247                register_irq_proc(irq, desc);
 248}
 249
 250