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