cregit-Linux how code gets into the kernel

Release 4.14 arch/mips/sgi-ip22/ip22-int.c

// SPDX-License-Identifier: GPL-2.0
/*
 * ip22-int.c: Routines for generic manipulation of the INT[23] ASIC
 *             found on INDY and Indigo2 workstations.
 *
 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
 * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
 * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
 *                    - Indigo2 changes
 *                    - Interrupt handling fixes
 * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org)
 */
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <linux/ftrace.h>

#include <asm/irq_cpu.h>
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>

/* So far nothing hangs here */

#undef USE_LIO3_IRQ


struct sgint_regs *sgint;


static char lc0msk_to_irqnr[256];

static char lc1msk_to_irqnr[256];

static char lc2msk_to_irqnr[256];

static char lc3msk_to_irqnr[256];

extern int ip22_eisa_init(void);


static void enable_local0_irq(struct irq_data *d) { /* don't allow mappable interrupt to be enabled from setup_irq, * we have our own way to do so */ if (d->irq != SGI_MAP_0_IRQ) sgint->imask0 |= (1 << (d->irq - SGINT_LOCAL0)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1541.67%125.00%
Ralf Bächle822.22%125.00%
Thomas Gleixner822.22%125.00%
Linus Torvalds513.89%125.00%
Total36100.00%4100.00%


static void disable_local0_irq(struct irq_data *d) { sgint->imask0 &= ~(1 << (d->irq - SGINT_LOCAL0)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1139.29%125.00%
Linus Torvalds1035.71%125.00%
Thomas Gleixner621.43%125.00%
Ralf Bächle13.57%125.00%
Total28100.00%4100.00%

static struct irq_chip ip22_local0_irq_type = { .name = "IP22 local 0", .irq_mask = disable_local0_irq, .irq_unmask = enable_local0_irq, };
static void enable_local1_irq(struct irq_data *d) { /* don't allow mappable interrupt to be enabled from setup_irq, * we have our own way to do so */ if (d->irq != SGI_MAP_1_IRQ) sgint->imask1 |= (1 << (d->irq - SGINT_LOCAL1)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1130.56%125.00%
Linus Torvalds925.00%125.00%
Thomas Gleixner822.22%125.00%
Ralf Bächle822.22%125.00%
Total36100.00%4100.00%


static void disable_local1_irq(struct irq_data *d) { sgint->imask1 &= ~(1 << (d->irq - SGINT_LOCAL1)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1657.14%120.00%
Thomas Gleixner621.43%120.00%
Linus Torvalds (pre-git)414.29%120.00%
Dmitri Vorobiev13.57%120.00%
Ralf Bächle13.57%120.00%
Total28100.00%5100.00%

static struct irq_chip ip22_local1_irq_type = { .name = "IP22 local 1", .irq_mask = disable_local1_irq, .irq_unmask = enable_local1_irq, };
static void enable_local2_irq(struct irq_data *d) { sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); sgint->cmeimask0 |= (1 << (d->irq - SGINT_LOCAL2)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1434.15%125.00%
Ralf Bächle1434.15%125.00%
Linus Torvalds (pre-git)717.07%125.00%
Thomas Gleixner614.63%125.00%
Total41100.00%4100.00%


static void disable_local2_irq(struct irq_data *d) { sgint->cmeimask0 &= ~(1 << (d->irq - SGINT_LOCAL2)); if (!sgint->cmeimask0) sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); }

Contributors

PersonTokensPropCommitsCommitProp
Ralf Bächle2346.00%120.00%
Linus Torvalds1734.00%120.00%
Thomas Gleixner612.00%120.00%
Linus Torvalds (pre-git)36.00%120.00%
Dmitri Vorobiev12.00%120.00%
Total50100.00%5100.00%

static struct irq_chip ip22_local2_irq_type = { .name = "IP22 local 2", .irq_mask = disable_local2_irq, .irq_unmask = enable_local2_irq, };
static void enable_local3_irq(struct irq_data *d) { sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); sgint->cmeimask1 |= (1 << (d->irq - SGINT_LOCAL3)); }

Contributors

PersonTokensPropCommitsCommitProp
Ralf Bächle2663.41%125.00%
Linus Torvalds (pre-git)717.07%125.00%
Thomas Gleixner614.63%125.00%
Linus Torvalds24.88%125.00%
Total41100.00%4100.00%


static void disable_local3_irq(struct irq_data *d) { sgint->cmeimask1 &= ~(1 << (d->irq - SGINT_LOCAL3)); if (!sgint->cmeimask1) sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); }

Contributors

PersonTokensPropCommitsCommitProp
Ralf Bächle3570.00%120.00%
Linus Torvalds612.00%120.00%
Thomas Gleixner612.00%120.00%
Linus Torvalds (pre-git)24.00%120.00%
Dmitri Vorobiev12.00%120.00%
Total50100.00%5100.00%

static struct irq_chip ip22_local3_irq_type = { .name = "IP22 local 3", .irq_mask = disable_local3_irq, .irq_unmask = enable_local3_irq, };
static void indy_local0_irqdispatch(void) { u8 mask = sgint->istat0 & sgint->imask0; u8 mask2; int irq; if (mask & SGINT_ISTAT0_LIO2) { mask2 = sgint->vmeistat & sgint->cmeimask0; irq = lc2msk_to_irqnr[mask2]; } else irq = lc0msk_to_irqnr[mask]; /* * workaround for INT2 bug; if irq == 0, INT2 has seen a fifo full * irq, but failed to latch it into status register */ if (irq) do_IRQ(irq); else do_IRQ(SGINT_LOCAL0 + 0); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5268.42%228.57%
Ralf Bächle1317.11%342.86%
Thomas Bogendoerfer911.84%114.29%
Linus Torvalds22.63%114.29%
Total76100.00%7100.00%


static void indy_local1_irqdispatch(void) { u8 mask = sgint->istat1 & sgint->imask1; u8 mask2; int irq; if (mask & SGINT_ISTAT1_LIO3) { mask2 = sgint->vmeistat & sgint->cmeimask1; irq = lc3msk_to_irqnr[mask2]; } else irq = lc1msk_to_irqnr[mask]; /* if irq == 0, then the interrupt has already been cleared */ if (irq) do_IRQ(irq); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5276.47%233.33%
Ralf Bächle1522.06%350.00%
Linus Torvalds11.47%116.67%
Total68100.00%6100.00%

extern void ip22_be_interrupt(int irq);
static void __irq_entry indy_buserror_irq(void) { int irq = SGI_BUSERR_IRQ; irq_enter(); kstat_incr_irq_this_cpu(irq); ip22_be_interrupt(irq); irq_exit(); }

Contributors

PersonTokensPropCommitsCommitProp
Ralf Bächle2170.00%333.33%
Linus Torvalds (pre-git)516.67%333.33%
Mike Travis26.67%111.11%
Thomas Gleixner13.33%111.11%
Wu Zhangjin13.33%111.11%
Total30100.00%9100.00%

static struct irqaction local0_cascade = { .handler = no_action, .flags = IRQF_NO_THREAD, .name = "local0 cascade", }; static struct irqaction local1_cascade = { .handler = no_action, .flags = IRQF_NO_THREAD, .name = "local1 cascade", }; static struct irqaction buserr = { .handler = no_action, .flags = IRQF_NO_THREAD, .name = "Bus Error", }; static struct irqaction map0_cascade = { .handler = no_action, .flags = IRQF_NO_THREAD, .name = "mapable0 cascade", }; #ifdef USE_LIO3_IRQ static struct irqaction map1_cascade = { .handler = no_action, .flags = IRQF_NO_THREAD, .name = "mapable1 cascade", }; #define SGI_INTERRUPTS SGINT_END #else #define SGI_INTERRUPTS SGINT_LOCAL3 #endif extern void indy_8254timer_irq(void); /* * IRQs on the INDY look basically (barring software IRQs which we don't use * at all) like: * * MIPS IRQ Source * -------- ------ * 0 Software (ignored) * 1 Software (ignored) * 2 Local IRQ level zero * 3 Local IRQ level one * 4 8254 Timer zero * 5 8254 Timer one * 6 Bus Error * 7 R4k timer (what we use) * * We handle the IRQ according to _our_ priority which is: * * Highest ---- R4k Timer * Local IRQ zero * Local IRQ one * Bus Error * 8254 Timer zero * Lowest ---- 8254 Timer one * * then we just return, if multiple IRQs are pending then we will just take * another exception, big deal. */
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause(); /* * First we check for r4k counter/timer IRQ. */ if (pending & CAUSEF_IP7) do_IRQ(SGI_TIMER_IRQ); else if (pending & CAUSEF_IP2) indy_local0_irqdispatch(); else if (pending & CAUSEF_IP3) indy_local1_irqdispatch(); else if (pending & CAUSEF_IP6) indy_buserror_irq(); else if (pending & (CAUSEF_IP4 | CAUSEF_IP5)) indy_8254timer_irq(); }

Contributors

PersonTokensPropCommitsCommitProp
Ralf Bächle7195.95%480.00%
Thiemo Seufer34.05%120.00%
Total74100.00%5100.00%


void __init arch_init_irq(void) { int i; /* Init local mask --> irq tables. */ for (i = 0; i < 256; i++) { if (i & 0x80) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7; } else if (i & 0x40) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6; } else if (i & 0x20) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5; } else if (i & 0x10) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4; } else if (i & 0x08) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3; } else if (i & 0x04) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2; } else if (i & 0x02) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1; } else if (i & 0x01) { lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0; lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0; lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0; lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0; } else { lc0msk_to_irqnr[i] = 0; lc1msk_to_irqnr[i] = 0; lc2msk_to_irqnr[i] = 0; lc3msk_to_irqnr[i] = 0; } } /* Mask out all interrupts. */ sgint->imask0 = 0; sgint->imask1 = 0; sgint->cmeimask0 = 0; sgint->cmeimask1 = 0; /* init CPU irqs */ mips_cpu_irq_init(); for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) { struct irq_chip *handler; if (i < SGINT_LOCAL1) handler = &ip22_local0_irq_type; else if (i < SGINT_LOCAL2) handler = &ip22_local1_irq_type; else if (i < SGINT_LOCAL3) handler = &ip22_local2_irq_type; else handler = &ip22_local3_irq_type; irq_set_chip_and_handler(i, handler, handle_level_irq); } /* vector handler. this register the IRQ as non-sharable */ setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade); setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade); setup_irq(SGI_BUSERR_IRQ, &buserr); /* cascade in cascade. i love Indy ;-) */ setup_irq(SGI_MAP_0_IRQ, &map0_cascade); #ifdef USE_LIO3_IRQ setup_irq(SGI_MAP_1_IRQ, &map1_cascade); #endif #ifdef CONFIG_EISA if (ip22_is_fullhouse()) /* Only Indigo-2 has EISA stuff */ ip22_eisa_init(); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)34960.49%220.00%
Ralf Bächle16127.90%330.00%
Linus Torvalds6010.40%110.00%
Atsushi Nemoto61.04%330.00%
Thomas Gleixner10.17%110.00%
Total577100.00%10100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Ralf Bächle58140.52%828.57%
Linus Torvalds (pre-git)56939.68%517.86%
Linus Torvalds17812.41%13.57%
Thomas Gleixner624.32%310.71%
Atsushi Nemoto171.19%414.29%
Wu Zhangjin90.63%27.14%
Thomas Bogendoerfer90.63%13.57%
Dmitri Vorobiev30.21%13.57%
Thiemo Seufer30.21%13.57%
Mike Travis20.14%13.57%
Greg Kroah-Hartman10.07%13.57%
Total1434100.00%28100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.