LCOV - code coverage report
Current view: top level - kernel/irq - debugfs.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 14 85 16.5 %
Date: 2020-09-30 20:25:40 Functions: 2 10 20.0 %
Branches: 6 40 15.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : // Copyright 2017 Thomas Gleixner <tglx@linutronix.de>
       3                 :            : 
       4                 :            : #include <linux/irqdomain.h>
       5                 :            : #include <linux/irq.h>
       6                 :            : #include <linux/uaccess.h>
       7                 :            : 
       8                 :            : #include "internals.h"
       9                 :            : 
      10                 :            : static struct dentry *irq_dir;
      11                 :            : 
      12                 :            : struct irq_bit_descr {
      13                 :            :         unsigned int    mask;
      14                 :            :         char            *name;
      15                 :            : };
      16                 :            : #define BIT_MASK_DESCR(m)       { .mask = m, .name = #m }
      17                 :            : 
      18                 :          0 : static void irq_debug_show_bits(struct seq_file *m, int ind, unsigned int state,
      19                 :            :                                 const struct irq_bit_descr *sd, int size)
      20                 :            : {
      21                 :            :         int i;
      22                 :            : 
      23         [ #  # ]:          0 :         for (i = 0; i < size; i++, sd++) {
      24         [ #  # ]:          0 :                 if (state & sd->mask)
      25                 :          0 :                         seq_printf(m, "%*s%s\n", ind + 12, "", sd->name);
      26                 :            :         }
      27                 :          0 : }
      28                 :            : 
      29                 :            : #ifdef CONFIG_SMP
      30                 :          0 : static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc)
      31                 :            : {
      32                 :            :         struct irq_data *data = irq_desc_get_irq_data(desc);
      33                 :            :         struct cpumask *msk;
      34                 :            : 
      35                 :            :         msk = irq_data_get_affinity_mask(data);
      36                 :          0 :         seq_printf(m, "affinity: %*pbl\n", cpumask_pr_args(msk));
      37                 :            : #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
      38                 :            :         msk = irq_data_get_effective_affinity_mask(data);
      39                 :          0 :         seq_printf(m, "effectiv: %*pbl\n", cpumask_pr_args(msk));
      40                 :            : #endif
      41                 :            : #ifdef CONFIG_GENERIC_PENDING_IRQ
      42                 :            :         msk = desc->pending_mask;
      43                 :            :         seq_printf(m, "pending:  %*pbl\n", cpumask_pr_args(msk));
      44                 :            : #endif
      45                 :          0 : }
      46                 :            : #else
      47                 :            : static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) { }
      48                 :            : #endif
      49                 :            : 
      50                 :            : static const struct irq_bit_descr irqchip_flags[] = {
      51                 :            :         BIT_MASK_DESCR(IRQCHIP_SET_TYPE_MASKED),
      52                 :            :         BIT_MASK_DESCR(IRQCHIP_EOI_IF_HANDLED),
      53                 :            :         BIT_MASK_DESCR(IRQCHIP_MASK_ON_SUSPEND),
      54                 :            :         BIT_MASK_DESCR(IRQCHIP_ONOFFLINE_ENABLED),
      55                 :            :         BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE),
      56                 :            :         BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
      57                 :            :         BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
      58                 :            :         BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
      59                 :            :         BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
      60                 :            : };
      61                 :            : 
      62                 :            : static void
      63                 :          0 : irq_debug_show_chip(struct seq_file *m, struct irq_data *data, int ind)
      64                 :            : {
      65                 :          0 :         struct irq_chip *chip = data->chip;
      66                 :            : 
      67         [ #  # ]:          0 :         if (!chip) {
      68                 :          0 :                 seq_printf(m, "chip: None\n");
      69                 :          0 :                 return;
      70                 :            :         }
      71                 :          0 :         seq_printf(m, "%*schip:    %s\n", ind, "", chip->name);
      72                 :          0 :         seq_printf(m, "%*sflags:   0x%lx\n", ind + 1, "", chip->flags);
      73                 :          0 :         irq_debug_show_bits(m, ind, chip->flags, irqchip_flags,
      74                 :            :                             ARRAY_SIZE(irqchip_flags));
      75                 :            : }
      76                 :            : 
      77                 :            : static void
      78                 :          0 : irq_debug_show_data(struct seq_file *m, struct irq_data *data, int ind)
      79                 :            : {
      80         [ #  # ]:          0 :         seq_printf(m, "%*sdomain:  %s\n", ind, "",
      81                 :          0 :                    data->domain ? data->domain->name : "");
      82                 :          0 :         seq_printf(m, "%*shwirq:   0x%lx\n", ind + 1, "", data->hwirq);
      83                 :          0 :         irq_debug_show_chip(m, data, ind + 1);
      84   [ #  #  #  #  :          0 :         if (data->domain && data->domain->ops && data->domain->ops->debug_show)
                   #  # ]
      85                 :          0 :                 data->domain->ops->debug_show(m, NULL, data, ind + 1);
      86                 :            : #ifdef  CONFIG_IRQ_DOMAIN_HIERARCHY
      87         [ #  # ]:          0 :         if (!data->parent_data)
      88                 :          0 :                 return;
      89                 :          0 :         seq_printf(m, "%*sparent:\n", ind + 1, "");
      90                 :          0 :         irq_debug_show_data(m, data->parent_data, ind + 4);
      91                 :            : #endif
      92                 :            : }
      93                 :            : 
      94                 :            : static const struct irq_bit_descr irqdata_states[] = {
      95                 :            :         BIT_MASK_DESCR(IRQ_TYPE_EDGE_RISING),
      96                 :            :         BIT_MASK_DESCR(IRQ_TYPE_EDGE_FALLING),
      97                 :            :         BIT_MASK_DESCR(IRQ_TYPE_LEVEL_HIGH),
      98                 :            :         BIT_MASK_DESCR(IRQ_TYPE_LEVEL_LOW),
      99                 :            :         BIT_MASK_DESCR(IRQD_LEVEL),
     100                 :            : 
     101                 :            :         BIT_MASK_DESCR(IRQD_ACTIVATED),
     102                 :            :         BIT_MASK_DESCR(IRQD_IRQ_STARTED),
     103                 :            :         BIT_MASK_DESCR(IRQD_IRQ_DISABLED),
     104                 :            :         BIT_MASK_DESCR(IRQD_IRQ_MASKED),
     105                 :            :         BIT_MASK_DESCR(IRQD_IRQ_INPROGRESS),
     106                 :            : 
     107                 :            :         BIT_MASK_DESCR(IRQD_PER_CPU),
     108                 :            :         BIT_MASK_DESCR(IRQD_NO_BALANCING),
     109                 :            : 
     110                 :            :         BIT_MASK_DESCR(IRQD_SINGLE_TARGET),
     111                 :            :         BIT_MASK_DESCR(IRQD_MOVE_PCNTXT),
     112                 :            :         BIT_MASK_DESCR(IRQD_AFFINITY_SET),
     113                 :            :         BIT_MASK_DESCR(IRQD_SETAFFINITY_PENDING),
     114                 :            :         BIT_MASK_DESCR(IRQD_AFFINITY_MANAGED),
     115                 :            :         BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN),
     116                 :            :         BIT_MASK_DESCR(IRQD_CAN_RESERVE),
     117                 :            :         BIT_MASK_DESCR(IRQD_MSI_NOMASK_QUIRK),
     118                 :            : 
     119                 :            :         BIT_MASK_DESCR(IRQD_FORWARDED_TO_VCPU),
     120                 :            : 
     121                 :            :         BIT_MASK_DESCR(IRQD_WAKEUP_STATE),
     122                 :            :         BIT_MASK_DESCR(IRQD_WAKEUP_ARMED),
     123                 :            : };
     124                 :            : 
     125                 :            : static const struct irq_bit_descr irqdesc_states[] = {
     126                 :            :         BIT_MASK_DESCR(_IRQ_NOPROBE),
     127                 :            :         BIT_MASK_DESCR(_IRQ_NOREQUEST),
     128                 :            :         BIT_MASK_DESCR(_IRQ_NOTHREAD),
     129                 :            :         BIT_MASK_DESCR(_IRQ_NOAUTOEN),
     130                 :            :         BIT_MASK_DESCR(_IRQ_NESTED_THREAD),
     131                 :            :         BIT_MASK_DESCR(_IRQ_PER_CPU_DEVID),
     132                 :            :         BIT_MASK_DESCR(_IRQ_IS_POLLED),
     133                 :            :         BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY),
     134                 :            : };
     135                 :            : 
     136                 :            : static const struct irq_bit_descr irqdesc_istates[] = {
     137                 :            :         BIT_MASK_DESCR(IRQS_AUTODETECT),
     138                 :            :         BIT_MASK_DESCR(IRQS_SPURIOUS_DISABLED),
     139                 :            :         BIT_MASK_DESCR(IRQS_POLL_INPROGRESS),
     140                 :            :         BIT_MASK_DESCR(IRQS_ONESHOT),
     141                 :            :         BIT_MASK_DESCR(IRQS_REPLAY),
     142                 :            :         BIT_MASK_DESCR(IRQS_WAITING),
     143                 :            :         BIT_MASK_DESCR(IRQS_PENDING),
     144                 :            :         BIT_MASK_DESCR(IRQS_SUSPENDED),
     145                 :            :         BIT_MASK_DESCR(IRQS_NMI),
     146                 :            : };
     147                 :            : 
     148                 :            : 
     149                 :          0 : static int irq_debug_show(struct seq_file *m, void *p)
     150                 :            : {
     151                 :          0 :         struct irq_desc *desc = m->private;
     152                 :            :         struct irq_data *data;
     153                 :            : 
     154                 :          0 :         raw_spin_lock_irq(&desc->lock);
     155                 :            :         data = irq_desc_get_irq_data(desc);
     156                 :          0 :         seq_printf(m, "handler:  %ps\n", desc->handle_irq);
     157                 :          0 :         seq_printf(m, "device:   %s\n", desc->dev_name);
     158                 :          0 :         seq_printf(m, "status:   0x%08x\n", desc->status_use_accessors);
     159                 :          0 :         irq_debug_show_bits(m, 0, desc->status_use_accessors, irqdesc_states,
     160                 :            :                             ARRAY_SIZE(irqdesc_states));
     161                 :          0 :         seq_printf(m, "istate:   0x%08x\n", desc->istate);
     162                 :          0 :         irq_debug_show_bits(m, 0, desc->istate, irqdesc_istates,
     163                 :            :                             ARRAY_SIZE(irqdesc_istates));
     164                 :          0 :         seq_printf(m, "ddepth:   %u\n", desc->depth);
     165                 :          0 :         seq_printf(m, "wdepth:   %u\n", desc->wake_depth);
     166                 :          0 :         seq_printf(m, "dstate:   0x%08x\n", irqd_get(data));
     167                 :          0 :         irq_debug_show_bits(m, 0, irqd_get(data), irqdata_states,
     168                 :            :                             ARRAY_SIZE(irqdata_states));
     169                 :          0 :         seq_printf(m, "node:     %d\n", irq_data_get_node(data));
     170                 :          0 :         irq_debug_show_masks(m, desc);
     171                 :          0 :         irq_debug_show_data(m, data, 0);
     172                 :          0 :         raw_spin_unlock_irq(&desc->lock);
     173                 :          0 :         return 0;
     174                 :            : }
     175                 :            : 
     176                 :          0 : static int irq_debug_open(struct inode *inode, struct file *file)
     177                 :            : {
     178                 :          0 :         return single_open(file, irq_debug_show, inode->i_private);
     179                 :            : }
     180                 :            : 
     181                 :          0 : static ssize_t irq_debug_write(struct file *file, const char __user *user_buf,
     182                 :            :                                size_t count, loff_t *ppos)
     183                 :            : {
     184                 :          0 :         struct irq_desc *desc = file_inode(file)->i_private;
     185                 :          0 :         char buf[8] = { 0, };
     186                 :            :         size_t size;
     187                 :            : 
     188                 :          0 :         size = min(sizeof(buf) - 1, count);
     189         [ #  # ]:          0 :         if (copy_from_user(buf, user_buf, size))
     190                 :            :                 return -EFAULT;
     191                 :            : 
     192         [ #  # ]:          0 :         if (!strncmp(buf, "trigger", size)) {
     193                 :            :                 unsigned long flags;
     194                 :            :                 int err;
     195                 :            : 
     196                 :            :                 /* Try the HW interface first */
     197                 :          0 :                 err = irq_set_irqchip_state(irq_desc_get_irq(desc),
     198                 :            :                                             IRQCHIP_STATE_PENDING, true);
     199         [ #  # ]:          0 :                 if (!err)
     200                 :          0 :                         return count;
     201                 :            : 
     202                 :            :                 /*
     203                 :            :                  * Otherwise, try to inject via the resend interface,
     204                 :            :                  * which may or may not succeed.
     205                 :            :                  */
     206                 :            :                 chip_bus_lock(desc);
     207                 :          0 :                 raw_spin_lock_irqsave(&desc->lock, flags);
     208                 :            : 
     209                 :            :                 /*
     210                 :            :                  * Don't allow injection when the interrupt is:
     211                 :            :                  *  - Level or NMI type
     212                 :            :                  *  - not activated
     213                 :            :                  *  - replaying already
     214                 :            :                  */
     215   [ #  #  #  # ]:          0 :                 if (irq_settings_is_level(desc) ||
     216         [ #  # ]:          0 :                     !irqd_is_activated(&desc->irq_data) ||
     217                 :          0 :                     (desc->istate & (IRQS_NMI | IRQS_REPLAY))) {
     218                 :            :                         err = -EINVAL;
     219                 :            :                 } else {
     220                 :          0 :                         desc->istate |= IRQS_PENDING;
     221                 :          0 :                         check_irq_resend(desc);
     222                 :            :                         err = 0;
     223                 :            :                 }
     224                 :            : 
     225                 :          0 :                 raw_spin_unlock_irqrestore(&desc->lock, flags);
     226                 :            :                 chip_bus_sync_unlock(desc);
     227                 :            : 
     228         [ #  # ]:          0 :                 return err ? err : count;
     229                 :            :         }
     230                 :            : 
     231                 :          0 :         return count;
     232                 :            : }
     233                 :            : 
     234                 :            : static const struct file_operations dfs_irq_ops = {
     235                 :            :         .open           = irq_debug_open,
     236                 :            :         .write          = irq_debug_write,
     237                 :            :         .read           = seq_read,
     238                 :            :         .llseek         = seq_lseek,
     239                 :            :         .release        = single_release,
     240                 :            : };
     241                 :            : 
     242                 :          0 : void irq_debugfs_copy_devname(int irq, struct device *dev)
     243                 :            : {
     244                 :          0 :         struct irq_desc *desc = irq_to_desc(irq);
     245                 :            :         const char *name = dev_name(dev);
     246                 :            : 
     247         [ #  # ]:          0 :         if (name)
     248                 :          0 :                 desc->dev_name = kstrdup(name, GFP_KERNEL);
     249                 :          0 : }
     250                 :            : 
     251                 :      65412 : void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc)
     252                 :            : {
     253                 :            :         char name [10];
     254                 :            : 
     255   [ +  +  +  -  :      65412 :         if (!irq_dir || !desc || desc->debugfs_file)
                   +  - ]
     256                 :      31050 :                 return;
     257                 :            : 
     258                 :      34362 :         sprintf(name, "%d", irq);
     259                 :      34362 :         desc->debugfs_file = debugfs_create_file(name, 0644, irq_dir, desc,
     260                 :            :                                                  &dfs_irq_ops);
     261                 :            : }
     262                 :            : 
     263                 :        207 : static int __init irq_debugfs_init(void)
     264                 :            : {
     265                 :            :         struct dentry *root_dir;
     266                 :            :         int irq;
     267                 :            : 
     268                 :        207 :         root_dir = debugfs_create_dir("irq", NULL);
     269                 :            : 
     270                 :        207 :         irq_domain_debugfs_init(root_dir);
     271                 :            : 
     272                 :        207 :         irq_dir = debugfs_create_dir("irqs", root_dir);
     273                 :            : 
     274                 :        207 :         irq_lock_sparse();
     275         [ +  + ]:      34569 :         for_each_active_irq(irq)
     276                 :      34362 :                 irq_add_debugfs_entry(irq, irq_to_desc(irq));
     277                 :        207 :         irq_unlock_sparse();
     278                 :            : 
     279                 :        207 :         return 0;
     280                 :            : }
     281                 :            : __initcall(irq_debugfs_init);

Generated by: LCOV version 1.14