diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2017-11-22 17:13:37 -0500 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2017-11-23 14:18:18 -0500 |
| commit | fd2fa6c18b729e19c51240453a521f76c766247e (patch) | |
| tree | 0b7e6579c27e997dfb74c88a1bfa66f19daf0766 | |
| parent | e2a5dca753d1cdc3212519023ed8a13e13f5495b (diff) | |
x86/PCI: Remove unused HyperTransport interrupt support
There are no in-tree callers of ht_create_irq(), the driver interface for
HyperTransport interrupts, left. Remove the unused entry point and all the
supporting code.
See 8b955b0dddb3 ("[PATCH] Initial generic hypertransport interrupt
support").
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-pci@vger.kernel.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Link: https://lkml.kernel.org/r/20171122221337.3877.23362.stgit@bhelgaas-glaptop.roam.corp.google.com
| -rw-r--r-- | arch/x86/include/asm/hw_irq.h | 8 | ||||
| -rw-r--r-- | arch/x86/include/asm/hypertransport.h | 46 | ||||
| -rw-r--r-- | arch/x86/include/asm/irqdomain.h | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/htirq.c | 198 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/vector.c | 5 | ||||
| -rw-r--r-- | drivers/pci/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/pci/Makefile | 3 | ||||
| -rw-r--r-- | drivers/pci/htirq.c | 135 | ||||
| -rw-r--r-- | include/linux/htirq.h | 39 | ||||
| -rw-r--r-- | include/linux/pci.h | 6 |
11 files changed, 2 insertions, 454 deletions
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index b80e46733909..2851077b6051 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
| @@ -99,14 +99,6 @@ struct irq_alloc_info { | |||
| 99 | void *dmar_data; | 99 | void *dmar_data; |
| 100 | }; | 100 | }; |
| 101 | #endif | 101 | #endif |
| 102 | #ifdef CONFIG_HT_IRQ | ||
| 103 | struct { | ||
| 104 | int ht_pos; | ||
| 105 | int ht_idx; | ||
| 106 | struct pci_dev *ht_dev; | ||
| 107 | void *ht_update; | ||
| 108 | }; | ||
| 109 | #endif | ||
| 110 | #ifdef CONFIG_X86_UV | 102 | #ifdef CONFIG_X86_UV |
| 111 | struct { | 103 | struct { |
| 112 | int uv_limit; | 104 | int uv_limit; |
diff --git a/arch/x86/include/asm/hypertransport.h b/arch/x86/include/asm/hypertransport.h deleted file mode 100644 index 5d55df352879..000000000000 --- a/arch/x86/include/asm/hypertransport.h +++ /dev/null | |||
| @@ -1,46 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _ASM_X86_HYPERTRANSPORT_H | ||
| 3 | #define _ASM_X86_HYPERTRANSPORT_H | ||
| 4 | |||
| 5 | /* | ||
| 6 | * Constants for x86 Hypertransport Interrupts. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #define HT_IRQ_LOW_BASE 0xf8000000 | ||
| 10 | |||
| 11 | #define HT_IRQ_LOW_VECTOR_SHIFT 16 | ||
| 12 | #define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000 | ||
| 13 | #define HT_IRQ_LOW_VECTOR(v) \ | ||
| 14 | (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK) | ||
| 15 | |||
| 16 | #define HT_IRQ_LOW_DEST_ID_SHIFT 8 | ||
| 17 | #define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00 | ||
| 18 | #define HT_IRQ_LOW_DEST_ID(v) \ | ||
| 19 | (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK) | ||
| 20 | |||
| 21 | #define HT_IRQ_LOW_DM_PHYSICAL 0x0000000 | ||
| 22 | #define HT_IRQ_LOW_DM_LOGICAL 0x0000040 | ||
| 23 | |||
| 24 | #define HT_IRQ_LOW_RQEOI_EDGE 0x0000000 | ||
| 25 | #define HT_IRQ_LOW_RQEOI_LEVEL 0x0000020 | ||
| 26 | |||
| 27 | |||
| 28 | #define HT_IRQ_LOW_MT_FIXED 0x0000000 | ||
| 29 | #define HT_IRQ_LOW_MT_ARBITRATED 0x0000004 | ||
| 30 | #define HT_IRQ_LOW_MT_SMI 0x0000008 | ||
| 31 | #define HT_IRQ_LOW_MT_NMI 0x000000c | ||
| 32 | #define HT_IRQ_LOW_MT_INIT 0x0000010 | ||
| 33 | #define HT_IRQ_LOW_MT_STARTUP 0x0000014 | ||
| 34 | #define HT_IRQ_LOW_MT_EXTINT 0x0000018 | ||
| 35 | #define HT_IRQ_LOW_MT_LINT1 0x000008c | ||
| 36 | #define HT_IRQ_LOW_MT_LINT0 0x0000098 | ||
| 37 | |||
| 38 | #define HT_IRQ_LOW_IRQ_MASKED 0x0000001 | ||
| 39 | |||
| 40 | |||
| 41 | #define HT_IRQ_HIGH_DEST_ID_SHIFT 0 | ||
| 42 | #define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff | ||
| 43 | #define HT_IRQ_HIGH_DEST_ID(v) \ | ||
| 44 | ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) | ||
| 45 | |||
| 46 | #endif /* _ASM_X86_HYPERTRANSPORT_H */ | ||
diff --git a/arch/x86/include/asm/irqdomain.h b/arch/x86/include/asm/irqdomain.h index f695cc6b8e1f..139feef467f7 100644 --- a/arch/x86/include/asm/irqdomain.h +++ b/arch/x86/include/asm/irqdomain.h | |||
| @@ -56,10 +56,4 @@ extern void arch_init_msi_domain(struct irq_domain *domain); | |||
| 56 | static inline void arch_init_msi_domain(struct irq_domain *domain) { } | 56 | static inline void arch_init_msi_domain(struct irq_domain *domain) { } |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| 59 | #ifdef CONFIG_HT_IRQ | ||
| 60 | extern void arch_init_htirq_domain(struct irq_domain *domain); | ||
| 61 | #else | ||
| 62 | static inline void arch_init_htirq_domain(struct irq_domain *domain) { } | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #endif | 59 | #endif |
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index a9e08924927e..a6fcaf16cdbf 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile | |||
| @@ -12,7 +12,6 @@ obj-y += hw_nmi.o | |||
| 12 | 12 | ||
| 13 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o | 13 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o |
| 14 | obj-$(CONFIG_PCI_MSI) += msi.o | 14 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 15 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
| 16 | obj-$(CONFIG_SMP) += ipi.o | 15 | obj-$(CONFIG_SMP) += ipi.o |
| 17 | 16 | ||
| 18 | ifeq ($(CONFIG_X86_64),y) | 17 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/apic/htirq.c b/arch/x86/kernel/apic/htirq.c deleted file mode 100644 index b07075dce8b7..000000000000 --- a/arch/x86/kernel/apic/htirq.c +++ /dev/null | |||
| @@ -1,198 +0,0 @@ | |||
| 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 | * Jiang Liu <jiang.liu@linux.intel.com> | ||
| 7 | * Add support of hierarchical irqdomain | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | #include <linux/mm.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/pci.h> | ||
| 18 | #include <linux/htirq.h> | ||
| 19 | #include <asm/irqdomain.h> | ||
| 20 | #include <asm/hw_irq.h> | ||
| 21 | #include <asm/apic.h> | ||
| 22 | #include <asm/hypertransport.h> | ||
| 23 | |||
| 24 | static struct irq_domain *htirq_domain; | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Hypertransport interrupt support | ||
| 28 | */ | ||
| 29 | static int | ||
| 30 | ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) | ||
| 31 | { | ||
| 32 | struct irq_data *parent = data->parent_data; | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | ret = parent->chip->irq_set_affinity(parent, mask, force); | ||
| 36 | if (ret >= 0) { | ||
| 37 | struct ht_irq_msg msg; | ||
| 38 | struct irq_cfg *cfg = irqd_cfg(data); | ||
| 39 | |||
| 40 | fetch_ht_irq_msg(data->irq, &msg); | ||
| 41 | msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | | ||
| 42 | HT_IRQ_LOW_DEST_ID_MASK); | ||
| 43 | msg.address_lo |= HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
| 44 | HT_IRQ_LOW_DEST_ID(cfg->dest_apicid); | ||
| 45 | msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
| 46 | msg.address_hi |= HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid); | ||
| 47 | write_ht_irq_msg(data->irq, &msg); | ||
| 48 | } | ||
| 49 | |||
| 50 | return ret; | ||
| 51 | } | ||
| 52 | |||
| 53 | static struct irq_chip ht_irq_chip = { | ||
| 54 | .name = "PCI-HT", | ||
| 55 | .irq_mask = mask_ht_irq, | ||
| 56 | .irq_unmask = unmask_ht_irq, | ||
| 57 | .irq_ack = irq_chip_ack_parent, | ||
| 58 | .irq_set_affinity = ht_set_affinity, | ||
| 59 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
| 60 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 61 | }; | ||
| 62 | |||
| 63 | static int htirq_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 64 | unsigned int nr_irqs, void *arg) | ||
| 65 | { | ||
| 66 | struct ht_irq_cfg *ht_cfg; | ||
| 67 | struct irq_alloc_info *info = arg; | ||
| 68 | struct pci_dev *dev; | ||
| 69 | irq_hw_number_t hwirq; | ||
| 70 | int ret; | ||
| 71 | |||
| 72 | if (nr_irqs > 1 || !info) | ||
| 73 | return -EINVAL; | ||
| 74 | |||
| 75 | dev = info->ht_dev; | ||
| 76 | hwirq = (info->ht_idx & 0xFF) | | ||
| 77 | PCI_DEVID(dev->bus->number, dev->devfn) << 8 | | ||
| 78 | (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 24; | ||
| 79 | if (irq_find_mapping(domain, hwirq) > 0) | ||
| 80 | return -EEXIST; | ||
| 81 | |||
| 82 | ht_cfg = kmalloc(sizeof(*ht_cfg), GFP_KERNEL); | ||
| 83 | if (!ht_cfg) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info); | ||
| 87 | if (ret < 0) { | ||
| 88 | kfree(ht_cfg); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Initialize msg to a value that will never match the first write. */ | ||
| 93 | ht_cfg->msg.address_lo = 0xffffffff; | ||
| 94 | ht_cfg->msg.address_hi = 0xffffffff; | ||
| 95 | ht_cfg->dev = info->ht_dev; | ||
| 96 | ht_cfg->update = info->ht_update; | ||
| 97 | ht_cfg->pos = info->ht_pos; | ||
| 98 | ht_cfg->idx = 0x10 + (info->ht_idx * 2); | ||
| 99 | irq_domain_set_info(domain, virq, hwirq, &ht_irq_chip, ht_cfg, | ||
| 100 | handle_edge_irq, ht_cfg, "edge"); | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static void htirq_domain_free(struct irq_domain *domain, unsigned int virq, | ||
| 106 | unsigned int nr_irqs) | ||
| 107 | { | ||
| 108 | struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq); | ||
| 109 | |||
| 110 | BUG_ON(nr_irqs != 1); | ||
| 111 | kfree(irq_data->chip_data); | ||
| 112 | irq_domain_free_irqs_top(domain, virq, nr_irqs); | ||
| 113 | } | ||
| 114 | |||
| 115 | static int htirq_domain_activate(struct irq_domain *domain, | ||
| 116 | struct irq_data *irq_data, bool early) | ||
| 117 | { | ||
| 118 | struct ht_irq_msg msg; | ||
| 119 | struct irq_cfg *cfg = irqd_cfg(irq_data); | ||
| 120 | |||
| 121 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid); | ||
| 122 | msg.address_lo = | ||
| 123 | HT_IRQ_LOW_BASE | | ||
| 124 | HT_IRQ_LOW_DEST_ID(cfg->dest_apicid) | | ||
| 125 | HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
| 126 | ((apic->irq_dest_mode == 0) ? | ||
| 127 | HT_IRQ_LOW_DM_PHYSICAL : | ||
| 128 | HT_IRQ_LOW_DM_LOGICAL) | | ||
| 129 | HT_IRQ_LOW_RQEOI_EDGE | | ||
| 130 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
| 131 | HT_IRQ_LOW_MT_FIXED : | ||
| 132 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
| 133 | HT_IRQ_LOW_IRQ_MASKED; | ||
| 134 | write_ht_irq_msg(irq_data->irq, &msg); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static void htirq_domain_deactivate(struct irq_domain *domain, | ||
| 139 | struct irq_data *irq_data) | ||
| 140 | { | ||
| 141 | struct ht_irq_msg msg; | ||
| 142 | |||
| 143 | memset(&msg, 0, sizeof(msg)); | ||
| 144 | write_ht_irq_msg(irq_data->irq, &msg); | ||
| 145 | } | ||
| 146 | |||
| 147 | static const struct irq_domain_ops htirq_domain_ops = { | ||
| 148 | .alloc = htirq_domain_alloc, | ||
| 149 | .free = htirq_domain_free, | ||
| 150 | .activate = htirq_domain_activate, | ||
| 151 | .deactivate = htirq_domain_deactivate, | ||
| 152 | }; | ||
| 153 | |||
| 154 | void __init arch_init_htirq_domain(struct irq_domain *parent) | ||
| 155 | { | ||
| 156 | struct fwnode_handle *fn; | ||
| 157 | |||
| 158 | if (disable_apic) | ||
| 159 | return; | ||
| 160 | |||
| 161 | fn = irq_domain_alloc_named_fwnode("PCI-HT"); | ||
| 162 | if (!fn) | ||
| 163 | goto warn; | ||
| 164 | |||
| 165 | htirq_domain = irq_domain_create_tree(fn, &htirq_domain_ops, NULL); | ||
| 166 | irq_domain_free_fwnode(fn); | ||
| 167 | if (!htirq_domain) | ||
| 168 | goto warn; | ||
| 169 | |||
| 170 | htirq_domain->parent = parent; | ||
| 171 | return; | ||
| 172 | |||
| 173 | warn: | ||
| 174 | pr_warn("Failed to initialize irqdomain for HTIRQ.\n"); | ||
| 175 | } | ||
| 176 | |||
| 177 | int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev, | ||
| 178 | ht_irq_update_t *update) | ||
| 179 | { | ||
| 180 | struct irq_alloc_info info; | ||
| 181 | |||
| 182 | if (!htirq_domain) | ||
| 183 | return -ENOSYS; | ||
| 184 | |||
| 185 | init_irq_alloc_info(&info, NULL); | ||
| 186 | info.ht_idx = idx; | ||
| 187 | info.ht_pos = pos; | ||
| 188 | info.ht_dev = dev; | ||
| 189 | info.ht_update = update; | ||
| 190 | |||
| 191 | return irq_domain_alloc_irqs(htirq_domain, 1, dev_to_node(&dev->dev), | ||
| 192 | &info); | ||
| 193 | } | ||
| 194 | |||
| 195 | void arch_teardown_ht_irq(unsigned int irq) | ||
| 196 | { | ||
| 197 | irq_domain_free_irqs(irq, 1); | ||
| 198 | } | ||
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 05c85e693a5d..6a823a25eaff 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Local APIC related interfaces to support IOAPIC, MSI, HT_IRQ etc. | 2 | * Local APIC related interfaces to support IOAPIC, MSI, etc. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo | 4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo |
| 5 | * Moved from arch/x86/kernel/apic/io_apic.c. | 5 | * Moved from arch/x86/kernel/apic/io_apic.c. |
| @@ -601,7 +601,7 @@ int __init arch_probe_nr_irqs(void) | |||
| 601 | nr_irqs = NR_VECTORS * nr_cpu_ids; | 601 | nr_irqs = NR_VECTORS * nr_cpu_ids; |
| 602 | 602 | ||
| 603 | nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids; | 603 | nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids; |
| 604 | #if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ) | 604 | #if defined(CONFIG_PCI_MSI) |
| 605 | /* | 605 | /* |
| 606 | * for MSI and HT dyn irq | 606 | * for MSI and HT dyn irq |
| 607 | */ | 607 | */ |
| @@ -663,7 +663,6 @@ int __init arch_early_irq_init(void) | |||
| 663 | irq_set_default_host(x86_vector_domain); | 663 | irq_set_default_host(x86_vector_domain); |
| 664 | 664 | ||
| 665 | arch_init_msi_domain(x86_vector_domain); | 665 | arch_init_msi_domain(x86_vector_domain); |
| 666 | arch_init_htirq_domain(x86_vector_domain); | ||
| 667 | 666 | ||
| 668 | BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL)); | 667 | BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL)); |
| 669 | 668 | ||
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index c32a77fc8b03..99ae5e30eabe 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
| @@ -71,15 +71,6 @@ config XEN_PCIDEV_FRONTEND | |||
| 71 | The PCI device frontend driver allows the kernel to import arbitrary | 71 | The PCI device frontend driver allows the kernel to import arbitrary |
| 72 | PCI devices from a PCI backend to support PCI driver domains. | 72 | PCI devices from a PCI backend to support PCI driver domains. |
| 73 | 73 | ||
| 74 | config HT_IRQ | ||
| 75 | bool "Interrupts on hypertransport devices" | ||
| 76 | default y | ||
| 77 | depends on PCI && X86_LOCAL_APIC | ||
| 78 | help | ||
| 79 | This allows native hypertransport devices to use interrupts. | ||
| 80 | |||
| 81 | If unsure say Y. | ||
| 82 | |||
| 83 | config PCI_ATS | 74 | config PCI_ATS |
| 84 | bool | 75 | bool |
| 85 | 76 | ||
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 80adbdbcecce..ab0104e0ffac 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
| @@ -24,9 +24,6 @@ endif | |||
| 24 | # Build the PCI MSI interrupt support | 24 | # Build the PCI MSI interrupt support |
| 25 | obj-$(CONFIG_PCI_MSI) += msi.o | 25 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 26 | 26 | ||
| 27 | # Build the Hypertransport interrupt support | ||
| 28 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
| 29 | |||
| 30 | obj-$(CONFIG_PCI_ATS) += ats.o | 27 | obj-$(CONFIG_PCI_ATS) += ats.o |
| 31 | obj-$(CONFIG_PCI_IOV) += iov.o | 28 | obj-$(CONFIG_PCI_IOV) += iov.o |
| 32 | 29 | ||
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c deleted file mode 100644 index bb88c26f5144..000000000000 --- a/drivers/pci/htirq.c +++ /dev/null | |||
| @@ -1,135 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * File: htirq.c | ||
| 4 | * Purpose: Hypertransport Interrupt Capability | ||
| 5 | * | ||
| 6 | * Copyright (C) 2006 Linux Networx | ||
| 7 | * Copyright (C) Eric Biederman <ebiederman@lnxi.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/pci.h> | ||
| 12 | #include <linux/spinlock.h> | ||
| 13 | #include <linux/export.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/htirq.h> | ||
| 16 | |||
| 17 | /* Global ht irq lock. | ||
| 18 | * | ||
| 19 | * This is needed to serialize access to the data port in hypertransport | ||
| 20 | * irq capability. | ||
| 21 | * | ||
| 22 | * With multiple simultaneous hypertransport irq devices it might pay | ||
| 23 | * to make this more fine grained. But start with simple, stupid, and correct. | ||
| 24 | */ | ||
| 25 | static DEFINE_SPINLOCK(ht_irq_lock); | ||
| 26 | |||
| 27 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | ||
| 28 | { | ||
| 29 | struct ht_irq_cfg *cfg = irq_get_handler_data(irq); | ||
| 30 | unsigned long flags; | ||
| 31 | |||
| 32 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 33 | if (cfg->msg.address_lo != msg->address_lo) { | ||
| 34 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
| 35 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo); | ||
| 36 | } | ||
| 37 | if (cfg->msg.address_hi != msg->address_hi) { | ||
| 38 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
| 39 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); | ||
| 40 | } | ||
| 41 | if (cfg->update) | ||
| 42 | cfg->update(cfg->dev, irq, msg); | ||
| 43 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 44 | cfg->msg = *msg; | ||
| 45 | } | ||
| 46 | |||
| 47 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | ||
| 48 | { | ||
| 49 | struct ht_irq_cfg *cfg = irq_get_handler_data(irq); | ||
| 50 | |||
| 51 | *msg = cfg->msg; | ||
| 52 | } | ||
| 53 | |||
| 54 | void mask_ht_irq(struct irq_data *data) | ||
| 55 | { | ||
| 56 | struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data); | ||
| 57 | struct ht_irq_msg msg = cfg->msg; | ||
| 58 | |||
| 59 | msg.address_lo |= 1; | ||
| 60 | write_ht_irq_msg(data->irq, &msg); | ||
| 61 | } | ||
| 62 | |||
| 63 | void unmask_ht_irq(struct irq_data *data) | ||
| 64 | { | ||
| 65 | struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data); | ||
| 66 | struct ht_irq_msg msg = cfg->msg; | ||
| 67 | |||
| 68 | msg.address_lo &= ~1; | ||
| 69 | write_ht_irq_msg(data->irq, &msg); | ||
| 70 | } | ||
| 71 | |||
| 72 | /** | ||
| 73 | * __ht_create_irq - create an irq and attach it to a device. | ||
| 74 | * @dev: The hypertransport device to find the irq capability on. | ||
| 75 | * @idx: Which of the possible irqs to attach to. | ||
| 76 | * @update: Function to be called when changing the htirq message | ||
| 77 | * | ||
| 78 | * The irq number of the new irq or a negative error value is returned. | ||
| 79 | */ | ||
| 80 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) | ||
| 81 | { | ||
| 82 | int max_irq, pos, irq; | ||
| 83 | unsigned long flags; | ||
| 84 | u32 data; | ||
| 85 | |||
| 86 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); | ||
| 87 | if (!pos) | ||
| 88 | return -EINVAL; | ||
| 89 | |||
| 90 | /* Verify the idx I want to use is in range */ | ||
| 91 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 92 | pci_write_config_byte(dev, pos + 2, 1); | ||
| 93 | pci_read_config_dword(dev, pos + 4, &data); | ||
| 94 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 95 | |||
| 96 | max_irq = (data >> 16) & 0xff; | ||
| 97 | if (idx > max_irq) | ||
| 98 | return -EINVAL; | ||
| 99 | |||
| 100 | irq = arch_setup_ht_irq(idx, pos, dev, update); | ||
| 101 | if (irq > 0) | ||
| 102 | dev_dbg(&dev->dev, "irq %d for HT\n", irq); | ||
| 103 | |||
| 104 | return irq; | ||
| 105 | } | ||
| 106 | EXPORT_SYMBOL(__ht_create_irq); | ||
| 107 | |||
| 108 | /** | ||
| 109 | * ht_create_irq - create an irq and attach it to a device. | ||
| 110 | * @dev: The hypertransport device to find the irq capability on. | ||
| 111 | * @idx: Which of the possible irqs to attach to. | ||
| 112 | * | ||
| 113 | * ht_create_irq needs to be called for all hypertransport devices | ||
| 114 | * that generate irqs. | ||
| 115 | * | ||
| 116 | * The irq number of the new irq or a negative error value is returned. | ||
| 117 | */ | ||
| 118 | int ht_create_irq(struct pci_dev *dev, int idx) | ||
| 119 | { | ||
| 120 | return __ht_create_irq(dev, idx, NULL); | ||
| 121 | } | ||
| 122 | EXPORT_SYMBOL(ht_create_irq); | ||
| 123 | |||
| 124 | /** | ||
| 125 | * ht_destroy_irq - destroy an irq created with ht_create_irq | ||
| 126 | * @irq: irq to be destroyed | ||
| 127 | * | ||
| 128 | * This reverses ht_create_irq removing the specified irq from | ||
| 129 | * existence. The irq should be free before this happens. | ||
| 130 | */ | ||
| 131 | void ht_destroy_irq(unsigned int irq) | ||
| 132 | { | ||
| 133 | arch_teardown_ht_irq(irq); | ||
| 134 | } | ||
| 135 | EXPORT_SYMBOL(ht_destroy_irq); | ||
diff --git a/include/linux/htirq.h b/include/linux/htirq.h deleted file mode 100644 index 127c39d815ba..000000000000 --- a/include/linux/htirq.h +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef LINUX_HTIRQ_H | ||
| 3 | #define LINUX_HTIRQ_H | ||
| 4 | |||
| 5 | struct pci_dev; | ||
| 6 | struct irq_data; | ||
| 7 | |||
| 8 | struct ht_irq_msg { | ||
| 9 | u32 address_lo; /* low 32 bits of the ht irq message */ | ||
| 10 | u32 address_hi; /* high 32 bits of the it irq message */ | ||
| 11 | }; | ||
| 12 | |||
| 13 | typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq, | ||
| 14 | struct ht_irq_msg *msg); | ||
| 15 | |||
| 16 | struct ht_irq_cfg { | ||
| 17 | struct pci_dev *dev; | ||
| 18 | /* Update callback used to cope with buggy hardware */ | ||
| 19 | ht_irq_update_t *update; | ||
| 20 | unsigned pos; | ||
| 21 | unsigned idx; | ||
| 22 | struct ht_irq_msg msg; | ||
| 23 | }; | ||
| 24 | |||
| 25 | /* Helper functions.. */ | ||
| 26 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); | ||
| 27 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); | ||
| 28 | void mask_ht_irq(struct irq_data *data); | ||
| 29 | void unmask_ht_irq(struct irq_data *data); | ||
| 30 | |||
| 31 | /* The arch hook for getting things started */ | ||
| 32 | int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev, | ||
| 33 | ht_irq_update_t *update); | ||
| 34 | void arch_teardown_ht_irq(unsigned int irq); | ||
| 35 | |||
| 36 | /* For drivers of buggy hardware */ | ||
| 37 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update); | ||
| 38 | |||
| 39 | #endif /* LINUX_HTIRQ_H */ | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index d16a7c037ec0..16287684dfe8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -1484,12 +1484,6 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { } | |||
| 1484 | static inline void pcie_ecrc_get_policy(char *str) { } | 1484 | static inline void pcie_ecrc_get_policy(char *str) { } |
| 1485 | #endif | 1485 | #endif |
| 1486 | 1486 | ||
| 1487 | #ifdef CONFIG_HT_IRQ | ||
| 1488 | /* The functions a driver should call */ | ||
| 1489 | int ht_create_irq(struct pci_dev *dev, int idx); | ||
| 1490 | void ht_destroy_irq(unsigned int irq); | ||
| 1491 | #endif /* CONFIG_HT_IRQ */ | ||
| 1492 | |||
| 1493 | #ifdef CONFIG_PCI_ATS | 1487 | #ifdef CONFIG_PCI_ATS |
| 1494 | /* Address Translation Service */ | 1488 | /* Address Translation Service */ |
| 1495 | void pci_ats_init(struct pci_dev *dev); | 1489 | void pci_ats_init(struct pci_dev *dev); |
