LCOV - code coverage report
Current view: top level - kernel/irq - resend.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 5 16 31.2 %
Date: 2023-04-06 08:38:28 Functions: 1 2 50.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
       4             :  * Copyright (C) 2005-2006, Thomas Gleixner
       5             :  *
       6             :  * This file contains the IRQ-resend code
       7             :  *
       8             :  * If the interrupt is waiting to be processed, we try to re-run it.
       9             :  * We can't directly run it from here since the caller might be in an
      10             :  * interrupt-protected region. Not all irq controller chips can
      11             :  * retrigger interrupts at the hardware level, so in those cases
      12             :  * we allow the resending of IRQs via a tasklet.
      13             :  */
      14             : 
      15             : #include <linux/irq.h>
      16             : #include <linux/module.h>
      17             : #include <linux/random.h>
      18             : #include <linux/interrupt.h>
      19             : 
      20             : #include "internals.h"
      21             : 
      22             : #ifdef CONFIG_HARDIRQS_SW_RESEND
      23             : 
      24             : /* Bitmap to handle software resend of interrupts: */
      25             : static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS);
      26             : 
      27             : /*
      28             :  * Run software resends of IRQ's
      29             :  */
      30             : static void resend_irqs(struct tasklet_struct *unused)
      31             : {
      32             :         struct irq_desc *desc;
      33             :         int irq;
      34             : 
      35             :         while (!bitmap_empty(irqs_resend, nr_irqs)) {
      36             :                 irq = find_first_bit(irqs_resend, nr_irqs);
      37             :                 clear_bit(irq, irqs_resend);
      38             :                 desc = irq_to_desc(irq);
      39             :                 if (!desc)
      40             :                         continue;
      41             :                 local_irq_disable();
      42             :                 desc->handle_irq(desc);
      43             :                 local_irq_enable();
      44             :         }
      45             : }
      46             : 
      47             : /* Tasklet to handle resend: */
      48             : static DECLARE_TASKLET(resend_tasklet, resend_irqs);
      49             : 
      50             : static int irq_sw_resend(struct irq_desc *desc)
      51             : {
      52             :         unsigned int irq = irq_desc_get_irq(desc);
      53             : 
      54             :         /*
      55             :          * Validate whether this interrupt can be safely injected from
      56             :          * non interrupt context
      57             :          */
      58             :         if (handle_enforce_irqctx(&desc->irq_data))
      59             :                 return -EINVAL;
      60             : 
      61             :         /*
      62             :          * If the interrupt is running in the thread context of the parent
      63             :          * irq we need to be careful, because we cannot trigger it
      64             :          * directly.
      65             :          */
      66             :         if (irq_settings_is_nested_thread(desc)) {
      67             :                 /*
      68             :                  * If the parent_irq is valid, we retrigger the parent,
      69             :                  * otherwise we do nothing.
      70             :                  */
      71             :                 if (!desc->parent_irq)
      72             :                         return -EINVAL;
      73             :                 irq = desc->parent_irq;
      74             :         }
      75             : 
      76             :         /* Set it pending and activate the softirq: */
      77             :         set_bit(irq, irqs_resend);
      78             :         tasklet_schedule(&resend_tasklet);
      79             :         return 0;
      80             : }
      81             : 
      82             : #else
      83             : static int irq_sw_resend(struct irq_desc *desc)
      84             : {
      85             :         return -EINVAL;
      86             : }
      87             : #endif
      88             : 
      89           0 : static int try_retrigger(struct irq_desc *desc)
      90             : {
      91           0 :         if (desc->irq_data.chip->irq_retrigger)
      92           0 :                 return desc->irq_data.chip->irq_retrigger(&desc->irq_data);
      93             : 
      94             : #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
      95           0 :         return irq_chip_retrigger_hierarchy(&desc->irq_data);
      96             : #else
      97             :         return 0;
      98             : #endif
      99             : }
     100             : 
     101             : /*
     102             :  * IRQ resend
     103             :  *
     104             :  * Is called with interrupts disabled and desc->lock held.
     105             :  */
     106           2 : int check_irq_resend(struct irq_desc *desc, bool inject)
     107             : {
     108           2 :         int err = 0;
     109             : 
     110             :         /*
     111             :          * We do not resend level type interrupts. Level type interrupts
     112             :          * are resent by hardware when they are still active. Clear the
     113             :          * pending bit so suspend/resume does not get confused.
     114             :          */
     115           4 :         if (irq_settings_is_level(desc)) {
     116           0 :                 desc->istate &= ~IRQS_PENDING;
     117           0 :                 return -EINVAL;
     118             :         }
     119             : 
     120           2 :         if (desc->istate & IRQS_REPLAY)
     121             :                 return -EBUSY;
     122             : 
     123           2 :         if (!(desc->istate & IRQS_PENDING) && !inject)
     124             :                 return 0;
     125             : 
     126           0 :         desc->istate &= ~IRQS_PENDING;
     127             : 
     128           0 :         if (!try_retrigger(desc))
     129           0 :                 err = irq_sw_resend(desc);
     130             : 
     131             :         /* If the retrigger was successful, mark it with the REPLAY bit */
     132           0 :         if (!err)
     133           0 :                 desc->istate |= IRQS_REPLAY;
     134             :         return err;
     135             : }
     136             : 
     137             : #ifdef CONFIG_GENERIC_IRQ_INJECTION
     138             : /**
     139             :  * irq_inject_interrupt - Inject an interrupt for testing/error injection
     140             :  * @irq:        The interrupt number
     141             :  *
     142             :  * This function must only be used for debug and testing purposes!
     143             :  *
     144             :  * Especially on x86 this can cause a premature completion of an interrupt
     145             :  * affinity change causing the interrupt line to become stale. Very
     146             :  * unlikely, but possible.
     147             :  *
     148             :  * The injection can fail for various reasons:
     149             :  * - Interrupt is not activated
     150             :  * - Interrupt is NMI type or currently replaying
     151             :  * - Interrupt is level type
     152             :  * - Interrupt does not support hardware retrigger and software resend is
     153             :  *   either not enabled or not possible for the interrupt.
     154             :  */
     155             : int irq_inject_interrupt(unsigned int irq)
     156             : {
     157             :         struct irq_desc *desc;
     158             :         unsigned long flags;
     159             :         int err;
     160             : 
     161             :         /* Try the state injection hardware interface first */
     162             :         if (!irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true))
     163             :                 return 0;
     164             : 
     165             :         /* That failed, try via the resend mechanism */
     166             :         desc = irq_get_desc_buslock(irq, &flags, 0);
     167             :         if (!desc)
     168             :                 return -EINVAL;
     169             : 
     170             :         /*
     171             :          * Only try to inject when the interrupt is:
     172             :          *  - not NMI type
     173             :          *  - activated
     174             :          */
     175             :         if ((desc->istate & IRQS_NMI) || !irqd_is_activated(&desc->irq_data))
     176             :                 err = -EINVAL;
     177             :         else
     178             :                 err = check_irq_resend(desc, true);
     179             : 
     180             :         irq_put_desc_busunlock(desc, flags);
     181             :         return err;
     182             : }
     183             : EXPORT_SYMBOL_GPL(irq_inject_interrupt);
     184             : #endif

Generated by: LCOV version 1.14