diff options
| author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-10-27 04:12:03 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2014-12-16 08:08:17 -0500 |
| commit | c3468952f073a9d4efa1e60c04c6e640ed9cf9d0 (patch) | |
| tree | 656df20e6835f847c4181be6c6ef5e8d7879539d /arch/x86/kernel/apic | |
| parent | 443809828cb5ee0eae09060aa8d4b42b79dd4e0b (diff) | |
x86, irq: Move HT IRQ related code from io_apic.c into htirq.c
Create arch/x86/kernel/apic/htirq.c to host Hypertransport IRQ related
code, preparing for enabling hierarchy irqdomain.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Link: http://lkml.kernel.org/r/1414397531-28254-13-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/apic')
| -rw-r--r-- | arch/x86/kernel/apic/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/htirq.c | 107 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 92 |
3 files changed, 108 insertions, 92 deletions
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index aac300750f0e..8bb12ddc5db8 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile | |||
| @@ -7,6 +7,7 @@ obj-y += hw_nmi.o | |||
| 7 | 7 | ||
| 8 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o | 8 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o |
| 9 | obj-$(CONFIG_PCI_MSI) += msi.o | 9 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 10 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
| 10 | obj-$(CONFIG_SMP) += ipi.o | 11 | obj-$(CONFIG_SMP) += ipi.o |
| 11 | 12 | ||
| 12 | ifeq ($(CONFIG_X86_64),y) | 13 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/apic/htirq.c b/arch/x86/kernel/apic/htirq.c new file mode 100644 index 000000000000..a4980c5091f0 --- /dev/null +++ b/arch/x86/kernel/apic/htirq.c | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * Support Hypertransport IRQ | ||
| 3 | * | ||
| 4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo | ||
| 5 | * Moved from arch/x86/kernel/apic/io_apic.c. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | #include <linux/mm.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/htirq.h> | ||
| 17 | #include <asm/hw_irq.h> | ||
| 18 | #include <asm/apic.h> | ||
| 19 | #include <asm/hypertransport.h> | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Hypertransport interrupt support | ||
| 23 | */ | ||
| 24 | static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) | ||
| 25 | { | ||
| 26 | struct ht_irq_msg msg; | ||
| 27 | |||
| 28 | fetch_ht_irq_msg(irq, &msg); | ||
| 29 | |||
| 30 | msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); | ||
| 31 | msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
| 32 | |||
| 33 | msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); | ||
| 34 | msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); | ||
| 35 | |||
| 36 | write_ht_irq_msg(irq, &msg); | ||
| 37 | } | ||
| 38 | |||
| 39 | static int | ||
| 40 | ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) | ||
| 41 | { | ||
| 42 | struct irq_cfg *cfg = data->chip_data; | ||
| 43 | unsigned int dest; | ||
| 44 | int ret; | ||
| 45 | |||
| 46 | ret = apic_set_affinity(data, mask, &dest); | ||
| 47 | if (ret) | ||
| 48 | return ret; | ||
| 49 | |||
| 50 | target_ht_irq(data->irq, dest, cfg->vector); | ||
| 51 | return IRQ_SET_MASK_OK_NOCOPY; | ||
| 52 | } | ||
| 53 | |||
| 54 | static struct irq_chip ht_irq_chip = { | ||
| 55 | .name = "PCI-HT", | ||
| 56 | .irq_mask = mask_ht_irq, | ||
| 57 | .irq_unmask = unmask_ht_irq, | ||
| 58 | .irq_ack = apic_ack_edge, | ||
| 59 | .irq_set_affinity = ht_set_affinity, | ||
| 60 | .irq_retrigger = apic_retrigger_irq, | ||
| 61 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 62 | }; | ||
| 63 | |||
| 64 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | ||
| 65 | { | ||
| 66 | struct irq_cfg *cfg; | ||
| 67 | struct ht_irq_msg msg; | ||
| 68 | unsigned dest; | ||
| 69 | int err; | ||
| 70 | |||
| 71 | if (disable_apic) | ||
| 72 | return -ENXIO; | ||
| 73 | |||
| 74 | cfg = irq_cfg(irq); | ||
| 75 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | ||
| 76 | if (err) | ||
| 77 | return err; | ||
| 78 | |||
| 79 | err = apic->cpu_mask_to_apicid_and(cfg->domain, | ||
| 80 | apic->target_cpus(), &dest); | ||
| 81 | if (err) | ||
| 82 | return err; | ||
| 83 | |||
| 84 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | ||
| 85 | |||
| 86 | msg.address_lo = | ||
| 87 | HT_IRQ_LOW_BASE | | ||
| 88 | HT_IRQ_LOW_DEST_ID(dest) | | ||
| 89 | HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
| 90 | ((apic->irq_dest_mode == 0) ? | ||
| 91 | HT_IRQ_LOW_DM_PHYSICAL : | ||
| 92 | HT_IRQ_LOW_DM_LOGICAL) | | ||
| 93 | HT_IRQ_LOW_RQEOI_EDGE | | ||
| 94 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
| 95 | HT_IRQ_LOW_MT_FIXED : | ||
| 96 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
| 97 | HT_IRQ_LOW_IRQ_MASKED; | ||
| 98 | |||
| 99 | write_ht_irq_msg(irq, &msg); | ||
| 100 | |||
| 101 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, | ||
| 102 | handle_edge_irq, "edge"); | ||
| 103 | |||
| 104 | dev_dbg(&dev->dev, "irq %d for HT\n", irq); | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 653fe211e4ca..b1acb68e19c7 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 33 | #include <linux/syscore_ops.h> | 33 | #include <linux/syscore_ops.h> |
| 34 | #include <linux/irqdomain.h> | 34 | #include <linux/irqdomain.h> |
| 35 | #include <linux/htirq.h> | ||
| 36 | #include <linux/freezer.h> | 35 | #include <linux/freezer.h> |
| 37 | #include <linux/kthread.h> | 36 | #include <linux/kthread.h> |
| 38 | #include <linux/jiffies.h> /* time_after() */ | 37 | #include <linux/jiffies.h> /* time_after() */ |
| @@ -49,7 +48,6 @@ | |||
| 49 | #include <asm/dma.h> | 48 | #include <asm/dma.h> |
| 50 | #include <asm/timer.h> | 49 | #include <asm/timer.h> |
| 51 | #include <asm/i8259.h> | 50 | #include <asm/i8259.h> |
| 52 | #include <asm/hypertransport.h> | ||
| 53 | #include <asm/setup.h> | 51 | #include <asm/setup.h> |
| 54 | #include <asm/irq_remapping.h> | 52 | #include <asm/irq_remapping.h> |
| 55 | #include <asm/hw_irq.h> | 53 | #include <asm/hw_irq.h> |
| @@ -2450,96 +2448,6 @@ static int __init ioapic_init_ops(void) | |||
| 2450 | 2448 | ||
| 2451 | device_initcall(ioapic_init_ops); | 2449 | device_initcall(ioapic_init_ops); |
| 2452 | 2450 | ||
| 2453 | /* | ||
| 2454 | * Hypertransport interrupt support | ||
| 2455 | */ | ||
| 2456 | #ifdef CONFIG_HT_IRQ | ||
| 2457 | |||
| 2458 | static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) | ||
| 2459 | { | ||
| 2460 | struct ht_irq_msg msg; | ||
| 2461 | fetch_ht_irq_msg(irq, &msg); | ||
| 2462 | |||
| 2463 | msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); | ||
| 2464 | msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
| 2465 | |||
| 2466 | msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); | ||
| 2467 | msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); | ||
| 2468 | |||
| 2469 | write_ht_irq_msg(irq, &msg); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | static int | ||
| 2473 | ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) | ||
| 2474 | { | ||
| 2475 | struct irq_cfg *cfg = data->chip_data; | ||
| 2476 | unsigned int dest; | ||
| 2477 | int ret; | ||
| 2478 | |||
| 2479 | ret = apic_set_affinity(data, mask, &dest); | ||
| 2480 | if (ret) | ||
| 2481 | return ret; | ||
| 2482 | |||
| 2483 | target_ht_irq(data->irq, dest, cfg->vector); | ||
| 2484 | return IRQ_SET_MASK_OK_NOCOPY; | ||
| 2485 | } | ||
| 2486 | |||
| 2487 | static struct irq_chip ht_irq_chip = { | ||
| 2488 | .name = "PCI-HT", | ||
| 2489 | .irq_mask = mask_ht_irq, | ||
| 2490 | .irq_unmask = unmask_ht_irq, | ||
| 2491 | .irq_ack = apic_ack_edge, | ||
| 2492 | .irq_set_affinity = ht_set_affinity, | ||
| 2493 | .irq_retrigger = apic_retrigger_irq, | ||
| 2494 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 2495 | }; | ||
| 2496 | |||
| 2497 | int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | ||
| 2498 | { | ||
| 2499 | struct irq_cfg *cfg; | ||
| 2500 | struct ht_irq_msg msg; | ||
| 2501 | unsigned dest; | ||
| 2502 | int err; | ||
| 2503 | |||
| 2504 | if (disable_apic) | ||
| 2505 | return -ENXIO; | ||
| 2506 | |||
| 2507 | cfg = irq_cfg(irq); | ||
| 2508 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | ||
| 2509 | if (err) | ||
| 2510 | return err; | ||
| 2511 | |||
| 2512 | err = apic->cpu_mask_to_apicid_and(cfg->domain, | ||
| 2513 | apic->target_cpus(), &dest); | ||
| 2514 | if (err) | ||
| 2515 | return err; | ||
| 2516 | |||
| 2517 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); | ||
| 2518 | |||
| 2519 | msg.address_lo = | ||
| 2520 | HT_IRQ_LOW_BASE | | ||
| 2521 | HT_IRQ_LOW_DEST_ID(dest) | | ||
| 2522 | HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
| 2523 | ((apic->irq_dest_mode == 0) ? | ||
| 2524 | HT_IRQ_LOW_DM_PHYSICAL : | ||
| 2525 | HT_IRQ_LOW_DM_LOGICAL) | | ||
| 2526 | HT_IRQ_LOW_RQEOI_EDGE | | ||
| 2527 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
| 2528 | HT_IRQ_LOW_MT_FIXED : | ||
| 2529 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
| 2530 | HT_IRQ_LOW_IRQ_MASKED; | ||
| 2531 | |||
| 2532 | write_ht_irq_msg(irq, &msg); | ||
| 2533 | |||
| 2534 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, | ||
| 2535 | handle_edge_irq, "edge"); | ||
| 2536 | |||
| 2537 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); | ||
| 2538 | |||
| 2539 | return 0; | ||
| 2540 | } | ||
| 2541 | #endif /* CONFIG_HT_IRQ */ | ||
| 2542 | |||
| 2543 | static int | 2451 | static int |
| 2544 | io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) | 2452 | io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) |
| 2545 | { | 2453 | { |
