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/gfp.h>
  11#include <linux/proc_fs.h>
  12#include <linux/seq_file.h>
  13#include <linux/interrupt.h>
  14#include <linux/kernel_stat.h>
  15#include <linux/mutex.h>
  16
  17#include "internals.h"
  18
  19/*
  20 * Access rules:
  21 *
  22 * procfs protects read/write of /proc/irq/N/ files against a
  23 * concurrent free of the interrupt descriptor. remove_proc_entry()
  24 * immediately prevents new read/writes to happen and waits for
  25 * already running read/write functions to complete.
  26 *
  27 * We remove the proc entries first and then delete the interrupt
  28 * descriptor from the radix tree and free it. So it is guaranteed
  29 * that irq_to_desc(N) is valid as long as the read/writes are
  30 * permitted by procfs.
  31 *
  32 * The read from /proc/interrupts is a different problem because there
  33 * is no protection. So the lookup and the access to irqdesc
  34 * information must be protected by sparse_irq_lock.
  35 */
  36static struct proc_dir_entry *root_irq_dir;
  37
  38#ifdef CONFIG_SMP
  39
  40static int show_irq_affinity(int type, struct seq_file *m, void *v)
  41{
  42        struct irq_desc *desc = irq_to_desc((long)m->private);
  43        const struct cpumask *mask = desc->irq_common_data.affinity;
  44
  45#ifdef CONFIG_GENERIC_PENDING_IRQ
  46        if (irqd_is_setaffinity_pending(&desc->irq_data))
  47                mask = desc->pending_mask;
  48#endif
  49        if (type)
  50                seq_printf(m, "%*pbl\n", cpumask_pr_args(mask));
  51        else
  52                seq_printf(m, "%*pb\n", cpumask_pr_args(mask));
  53        return 0;
  54}
  55
  56static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
  57{
  58        struct irq_desc *desc = irq_to_desc((long)m->private);
  59        unsigned long flags;
  60        cpumask_var_t mask;
  61
  62        if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
  63                return -ENOMEM;
  64
  65        raw_spin_lock_irqsave(&desc->lock, flags);
  66        if (desc->affinity_hint)
  67                cpumask_copy(mask, desc->affinity_hint);
  68        raw_spin_unlock_irqrestore(&desc->lock, flags);
  69
  70        seq_printf(m, "%*pb\n", cpumask_pr_args(mask));
  71        free_cpumask_var(mask);
  72
  73        return 0;
  74}
  75
  76#ifndef is_affinity_mask_valid
  77#define is_affinity_mask_valid(val) 1
  78#endif
  79
  80int no_irq_affinity;
  81static int irq_affinity_proc_show(struct seq_file *m, void *v)
  82{
  83        return show_irq_affinity(0, m, v);
  84}
  85
  86static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
  87{
  88        return show_irq_affinity(1, m, v);
  89}
  90
  91
  92static ssize_t write_irq_affinity(int type, struct file *file,
  93                const char __user *buffer, size_t count, loff_t *pos)
  94{
  95        unsigned int irq = (int)(long)PDE_DATA(file_inode(file));
  96        cpumask_var_t new_value;
  97        int err;
  98
  99        if (!irq_can_set_affinity_usr(irq) || no_irq_affinity)
 100                return -EIO;
 101
 102        if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
 103                return -ENOMEM;
 104
 105        if (type)
 106                err = cpumask_parselist_user(buffer, count, new_value);
 107        else
 108                err = cpumask_parse_user(buffer, count, new_value);
 109        if (err)
 110                goto free_cpumask;
 111
 112        if (!is_affinity_mask_valid(new_value)) {
 113                err = -EINVAL;
 114                goto free_cpumask;
 115        }
 116
 117        /*
 118         * Do not allow disabling IRQs completely - it's a too easy
 119         * way to make the system unusable accidentally :-) At least
 120         * one online CPU still has to be targeted.
 121         */
 122        if (!cpumask_intersects(new_value, cpu_online_mask)) {
 123                /* Special case for empty set - allow the architecture
 124                   code to set default SMP affinity. */
 125                err = irq_select_affinity_usr(irq, new_value) ? -EINVAL : count;
 126        } else {
 127                irq_set_affinity(irq, new_value);
 128                err = count;
 129        }
 130
 131free_cpumask:
 132        free_cpumask_var(new_value);
 133        return err;
 134}
 135
 136static ssize_t irq_affinity_proc_write(struct file *file,
 137                const char __user *buffer, size_t count, loff_t *pos)
 138{
 139        return write_irq_affinity(0, file, buffer, count, pos);
 140}
 141
 142static ssize_t irq_affinity_list_proc_write(struct file *file,
 143                const char __user *buffer, size_t count, loff_t *pos)
 144{
 145        return write_irq_affinity(1, file, buffer, count, pos);
 146}
 147
 148static int irq_affinity_proc_open(struct inode *inode, struct file *file)
 149{
 150        return single_open(file, irq_affinity_proc_show, PDE_DATA(inode));
 151}
 152
 153static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)
 154{
 155        return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode));
 156}
 157
 158static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)
 159{
 160        return single_open(file, irq_affinity_hint_proc_show, PDE_DATA(inode));
 161}
 162
 163static const struct file_operations irq_affinity_proc_fops = {
 164        .open           = irq_affinity_proc_open,
 165        .read           = seq_read,
 166        .llseek         = seq_lseek,
 167        .release        = single_release,
 168        .write          = irq_affinity_proc_write,
 169};
 170
 171static const struct file_operations irq_affinity_hint_proc_fops = {
 172        .open           = irq_affinity_hint_proc_open,
 173        .read           = seq_read,
 174        .llseek         = seq_lseek,
 175        .release        = single_release,
 176};
 177
 178static const struct file_operations irq_affinity_list_proc_fops = {
 179        .open           = irq_affinity_list_proc_open,
 180        .read           = seq_read,
 181        .llseek         = seq_lseek,
 182        .release        = single_release,
 183        .write          = irq_affinity_list_proc_write,
 184};
 185
 186static int default_affinity_show(struct seq_file *m, void *v)
 187{
 188        seq_printf(m, "%*pb\n", cpumask_pr_args(irq_default_affinity));
 189        return 0;
 190}
 191
 192static ssize_t default_affinity_write(struct file *file,
 193                const char __user *buffer, size_t count, loff_t *ppos)
 194{
 195        cpumask_var_t new_value;
 196        int err;
 197
 198        if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
 199                return -ENOMEM;
 200
 201        err = cpumask_parse_user(buffer, count, new_value);
 202        if (err)
 203                goto out;
 204
 205        if (!is_affinity_mask_valid(new_value)) {
 206                err = -EINVAL;
 207                goto out;
 208        }
 209
 210        /*
 211         * Do not allow disabling IRQs completely - it's a too easy
 212         * way to make the system unusable accidentally :-) At least
 213         * one online CPU still has to be targeted.
 214         */
 215        if (!cpumask_intersects(new_value, cpu_online_mask)) {
 216                err = -EINVAL;
 217                goto out;
 218        }
 219
 220        cpumask_copy(irq_default_affinity, new_value);
 221        err = count;
 222
 223out:
 224        free_cpumask_var(new_value);
 225        return err;
 226}
 227
 228static int default_affinity_open(struct inode *inode, struct file *file)
 229{
 230        return single_open(file, default_affinity_show, PDE_DATA(inode));
 231}
 232
 233static const struct file_operations default_affinity_proc_fops = {
 234        .open           = default_affinity_open,
 235        .read           = seq_read,
 236        .llseek         = seq_lseek,
 237        .release        = single_release,
 238        .write          = default_affinity_write,
 239};
 240
 241static int irq_node_proc_show(struct seq_file *m, void *v)
 242{
 243        struct irq_desc *desc = irq_to_desc((long) m->private);
 244
 245        seq_printf(m, "%d\n", irq_desc_get_node(desc));
 246        return 0;
 247}
 248
 249static int irq_node_proc_open(struct inode *inode, struct file *file)
 250{
 251        return single_open(file, irq_node_proc_show, PDE_DATA(inode));
 252}
 253
 254static const struct file_operations irq_node_proc_fops = {
 255        .open           = irq_node_proc_open,
 256        .read           = seq_read,
 257        .llseek         = seq_lseek,
 258        .release        = single_release,
 259};
 260#endif
 261
 262static int irq_spurious_proc_show(struct seq_file *m, void *v)
 263{
 264        struct irq_desc *desc = irq_to_desc((long) m->private);
 265
 266        seq_printf(m, "count %u\n" "unhandled %u\n" "last_unhandled %u ms\n",
 267                   desc->irq_count, desc->irqs_unhandled,
 268                   jiffies_to_msecs(desc->last_unhandled));
 269        return 0;
 270}
 271
 272static int irq_spurious_proc_open(struct inode *inode, struct file *file)
 273{
 274        return single_open(file, irq_spurious_proc_show, PDE_DATA(inode));
 275}
 276
 277static const struct file_operations irq_spurious_proc_fops = {
 278        .open           = irq_spurious_proc_open,
 279        .read           = seq_read,
 280        .llseek         = seq_lseek,
 281        .release        = single_release,
 282};
 283
 284#define MAX_NAMELEN 128
 285
 286static int name_unique(unsigned int irq, struct irqaction *new_action)
 287{
 288        struct irq_desc *desc = irq_to_desc(irq);
 289        struct irqaction *action;
 290        unsigned long flags;
 291        int ret = 1;
 292
 293        raw_spin_lock_irqsave(&desc->lock, flags);
 294        for_each_action_of_desc(desc, action) {
 295                if ((action != new_action) && action->name &&
 296                                !strcmp(new_action->name, action->name)) {
 297                        ret = 0;
 298                        break;
 299                }
 300        }
 301        raw_spin_unlock_irqrestore(&desc->lock, flags);
 302        return ret;
 303}
 304
 305void register_handler_proc(unsigned int irq, struct irqaction *action)
 306{
 307        char name [MAX_NAMELEN];
 308        struct irq_desc *desc = irq_to_desc(irq);
 309
 310        if (!desc->dir || action->dir || !action->name ||
 311                                        !name_unique(irq, action))
 312                return;
 313
 314        snprintf(name, MAX_NAMELEN, "%s", action->name);
 315
 316        /* create /proc/irq/1234/handler/ */
 317        action->dir = proc_mkdir(name, desc->dir);
 318}
 319
 320#undef MAX_NAMELEN
 321
 322#define MAX_NAMELEN 10
 323
 324void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 325{
 326        static DEFINE_MUTEX(register_lock);
 327        char name [MAX_NAMELEN];
 328
 329        if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip))
 330                return;
 331
 332        /*
 333         * irq directories are registered only when a handler is
 334         * added, not when the descriptor is created, so multiple
 335         * tasks might try to register at the same time.
 336         */
 337        mutex_lock(&register_lock);
 338
 339        if (desc->dir)
 340                goto out_unlock;
 341
 342        sprintf(name, "%d", irq);
 343
 344        /* create /proc/irq/1234 */
 345        desc->dir = proc_mkdir(name, root_irq_dir);
 346        if (!desc->dir)
 347                goto out_unlock;
 348
 349#ifdef CONFIG_SMP
 350        /* create /proc/irq/<irq>/smp_affinity */
 351        proc_create_data("smp_affinity", 0644, desc->dir,
 352                         &irq_affinity_proc_fops, (void *)(long)irq);
 353
 354        /* create /proc/irq/<irq>/affinity_hint */
 355        proc_create_data("affinity_hint", 0444, desc->dir,
 356                         &irq_affinity_hint_proc_fops, (void *)(long)irq);
 357
 358        /* create /proc/irq/<irq>/smp_affinity_list */
 359        proc_create_data("smp_affinity_list", 0644, desc->dir,
 360                         &irq_affinity_list_proc_fops, (void *)(long)irq);
 361
 362        proc_create_data("node", 0444, desc->dir,
 363                         &irq_node_proc_fops, (void *)(long)irq);
 364#endif
 365
 366        proc_create_data("spurious", 0444, desc->dir,
 367                         &irq_spurious_proc_fops, (void *)(long)irq);
 368
 369out_unlock:
 370        mutex_unlock(&register_lock);
 371}
 372
 373void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
 374{
 375        char name [MAX_NAMELEN];
 376
 377        if (!root_irq_dir || !desc->dir)
 378                return;
 379#ifdef CONFIG_SMP
 380        remove_proc_entry("smp_affinity", desc->dir);
 381        remove_proc_entry("affinity_hint", desc->dir);
 382        remove_proc_entry("smp_affinity_list", desc->dir);
 383        remove_proc_entry("node", desc->dir);
 384#endif
 385        remove_proc_entry("spurious", desc->dir);
 386
 387        sprintf(name, "%u", irq);
 388        remove_proc_entry(name, root_irq_dir);
 389}
 390
 391#undef MAX_NAMELEN
 392
 393void unregister_handler_proc(unsigned int irq, struct irqaction *action)
 394{
 395        proc_remove(action->dir);
 396}
 397
 398static void register_default_affinity_proc(void)
 399{
 400#ifdef CONFIG_SMP
 401        proc_create("irq/default_smp_affinity", 0644, NULL,
 402                    &default_affinity_proc_fops);
 403#endif
 404}
 405
 406void init_irq_proc(void)
 407{
 408        unsigned int irq;
 409        struct irq_desc *desc;
 410
 411        /* create /proc/irq */
 412        root_irq_dir = proc_mkdir("irq", NULL);
 413        if (!root_irq_dir)
 414                return;
 415
 416        register_default_affinity_proc();
 417
 418        /*
 419         * Create entries for all existing IRQs.
 420         */
 421        for_each_irq_desc(irq, desc)
 422                register_irq_proc(irq, desc);
 423}
 424
 425#ifdef CONFIG_GENERIC_IRQ_SHOW
 426
 427int __weak arch_show_interrupts(struct seq_file *p, int prec)
 428{
 429        return 0;
 430}
 431
 432#ifndef ACTUAL_NR_IRQS
 433# define ACTUAL_NR_IRQS nr_irqs
 434#endif
 435
 436int show_interrupts(struct seq_file *p, void *v)
 437{
 438        static int prec;
 439
 440        unsigned long flags, any_count = 0;
 441        int i = *(loff_t *) v, j;
 442        struct irqaction *action;
 443        struct irq_desc *desc;
 444
 445        if (i > ACTUAL_NR_IRQS)
 446                return 0;
 447
 448        if (i == ACTUAL_NR_IRQS)
 449                return arch_show_interrupts(p, prec);
 450
 451        /* print header and calculate the width of the first column */
 452        if (i == 0) {
 453                for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
 454                        j *= 10;
 455
 456                seq_printf(p, "%*s", prec + 8, "");
 457                for_each_online_cpu(j)
 458                        seq_printf(p, "CPU%-8d", j);
 459                seq_putc(p, '\n');
 460        }
 461
 462        irq_lock_sparse();
 463        desc = irq_to_desc(i);
 464        if (!desc)
 465                goto outsparse;
 466
 467        raw_spin_lock_irqsave(&desc->lock, flags);
 468        for_each_online_cpu(j)
 469                any_count |= kstat_irqs_cpu(i, j);
 470        action = desc->action;
 471        if ((!action || irq_desc_is_chained(desc)) && !any_count)
 472                goto out;
 473
 474        seq_printf(p, "%*d: ", prec, i);
 475        for_each_online_cpu(j)
 476                seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 477
 478        if (desc->irq_data.chip) {
 479                if (desc->irq_data.chip->irq_print_chip)
 480                        desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
 481                else if (desc->irq_data.chip->name)
 482                        seq_printf(p, " %8s", desc->irq_data.chip->name);
 483                else
 484                        seq_printf(p, " %8s", "-");
 485        } else {
 486                seq_printf(p, " %8s", "None");
 487        }
 488        if (desc->irq_data.domain)
 489                seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq);
 490#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
 491        seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
 492#endif
 493        if (desc->name)
 494                seq_printf(p, "-%-8s", desc->name);
 495
 496        if (action) {
 497                seq_printf(p, "  %s", action->name);
 498                while ((action = action->next) != NULL)
 499                        seq_printf(p, ", %s", action->name);
 500        }
 501
 502        seq_putc(p, '\n');
 503out:
 504        raw_spin_unlock_irqrestore(&desc->lock, flags);
 505outsparse:
 506        irq_unlock_sparse();
 507        return 0;
 508}
 509#endif
 510