1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * MSI hooks for standard x86 apic 4 */ 5 6 #include <linux/pci.h> 7 #include <linux/irq.h> 8 #include <linux/msi.h> 9 #include <linux/dmar.h> 10 #include <asm/smp.h> 11 #include <asm/msidef.h> 12 13 static struct irq_chip ia64_msi_chip; 14 15 #ifdef CONFIG_SMP 16 static int ia64_set_msi_irq_affinity(struct irq_data *idata, 17 const cpumask_t *cpu_mask, bool force) 18 { 19 struct msi_msg msg; 20 u32 addr, data; 21 int cpu = cpumask_first_and(cpu_mask, cpu_online_mask); 22 unsigned int irq = idata->irq; 23 24 if (irq_prepare_move(irq, cpu)) 25 return -1; 26 27 __get_cached_msi_msg(irq_data_get_msi_desc(idata), &msg); 28 29 addr = msg.address_lo; 30 addr &= MSI_ADDR_DEST_ID_MASK; 31 addr |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu)); 32 msg.address_lo = addr; 33 34 data = msg.data; 35 data &= MSI_DATA_VECTOR_MASK; 36 data |= MSI_DATA_VECTOR(irq_to_vector(irq)); 37 msg.data = data; 38 39 pci_write_msi_msg(irq, &msg); 40 irq_data_update_affinity(idata, cpumask_of(cpu)); 41 42 return 0; 43 } 44 #endif /* CONFIG_SMP */ 45 46 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 47 { 48 struct msi_msg msg; 49 unsigned long dest_phys_id; 50 int irq, vector; 51 52 irq = create_irq(); 53 if (irq < 0) 54 return irq; 55 56 irq_set_msi_desc(irq, desc); 57 dest_phys_id = cpu_physical_id(cpumask_any_and(&(irq_to_domain(irq)), 58 cpu_online_mask)); 59 vector = irq_to_vector(irq); 60 61 msg.address_hi = 0; 62 msg.address_lo = 63 MSI_ADDR_HEADER | 64 MSI_ADDR_DEST_MODE_PHYS | 65 MSI_ADDR_REDIRECTION_CPU | 66 MSI_ADDR_DEST_ID_CPU(dest_phys_id); 67 68 msg.data = 69 MSI_DATA_TRIGGER_EDGE | 70 MSI_DATA_LEVEL_ASSERT | 71 MSI_DATA_DELIVERY_FIXED | 72 MSI_DATA_VECTOR(vector); 73 74 pci_write_msi_msg(irq, &msg); 75 irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); 76 77 return 0; 78 } 79 80 void arch_teardown_msi_irq(unsigned int irq) 81 { 82 destroy_irq(irq); 83 } 84 85 static void ia64_ack_msi_irq(struct irq_data *data) 86 { 87 irq_complete_move(data->irq); 88 irq_move_irq(data); 89 ia64_eoi(); 90 } 91 92 static int ia64_msi_retrigger_irq(struct irq_data *data) 93 { 94 unsigned int vector = irq_to_vector(data->irq); 95 ia64_resend_irq(vector); 96 97 return 1; 98 } 99 100 /* 101 * Generic ops used on most IA64 platforms. 102 */ 103 static struct irq_chip ia64_msi_chip = { 104 .name = "PCI-MSI", 105 .irq_mask = pci_msi_mask_irq, 106 .irq_unmask = pci_msi_unmask_irq, 107 .irq_ack = ia64_ack_msi_irq, 108 #ifdef CONFIG_SMP 109 .irq_set_affinity = ia64_set_msi_irq_affinity, 110 #endif 111 .irq_retrigger = ia64_msi_retrigger_irq, 112 }; 113 114 #ifdef CONFIG_INTEL_IOMMU 115 #ifdef CONFIG_SMP 116 static int dmar_msi_set_affinity(struct irq_data *data, 117 const struct cpumask *mask, bool force) 118 { 119 unsigned int irq = data->irq; 120 struct irq_cfg *cfg = irq_cfg + irq; 121 struct msi_msg msg; 122 int cpu = cpumask_first_and(mask, cpu_online_mask); 123 124 if (irq_prepare_move(irq, cpu)) 125 return -1; 126 127 dmar_msi_read(irq, &msg); 128 129 msg.data &= ~MSI_DATA_VECTOR_MASK; 130 msg.data |= MSI_DATA_VECTOR(cfg->vector); 131 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; 132 msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu)); 133 134 dmar_msi_write(irq, &msg); 135 irq_data_update_affinity(data, mask); 136 137 return 0; 138 } 139 #endif /* CONFIG_SMP */ 140 141 static struct irq_chip dmar_msi_type = { 142 .name = "DMAR_MSI", 143 .irq_unmask = dmar_msi_unmask, 144 .irq_mask = dmar_msi_mask, 145 .irq_ack = ia64_ack_msi_irq, 146 #ifdef CONFIG_SMP 147 .irq_set_affinity = dmar_msi_set_affinity, 148 #endif 149 .irq_retrigger = ia64_msi_retrigger_irq, 150 }; 151 152 static void 153 msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 154 { 155 struct irq_cfg *cfg = irq_cfg + irq; 156 unsigned dest; 157 158 dest = cpu_physical_id(cpumask_first_and(&(irq_to_domain(irq)), 159 cpu_online_mask)); 160 161 msg->address_hi = 0; 162 msg->address_lo = 163 MSI_ADDR_HEADER | 164 MSI_ADDR_DEST_MODE_PHYS | 165 MSI_ADDR_REDIRECTION_CPU | 166 MSI_ADDR_DEST_ID_CPU(dest); 167 168 msg->data = 169 MSI_DATA_TRIGGER_EDGE | 170 MSI_DATA_LEVEL_ASSERT | 171 MSI_DATA_DELIVERY_FIXED | 172 MSI_DATA_VECTOR(cfg->vector); 173 } 174 175 int dmar_alloc_hwirq(int id, int node, void *arg) 176 { 177 int irq; 178 struct msi_msg msg; 179 180 irq = create_irq(); 181 if (irq > 0) { 182 irq_set_handler_data(irq, arg); 183 irq_set_chip_and_handler_name(irq, &dmar_msi_type, 184 handle_edge_irq, "edge"); 185 msi_compose_msg(NULL, irq, &msg); 186 dmar_msi_write(irq, &msg); 187 } 188 189 return irq; 190 } 191 192 void dmar_free_hwirq(int irq) 193 { 194 irq_set_handler_data(irq, NULL); 195 destroy_irq(irq); 196 } 197 #endif /* CONFIG_INTEL_IOMMU */ 198 199