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 11 /* 12 * Shifts for APIC-based data 13 */ 14 15 #define MSI_DATA_VECTOR_SHIFT 0 16 #define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) 17 #define MSI_DATA_VECTOR_MASK 0xffffff00 18 19 #define MSI_DATA_DELIVERY_SHIFT 8 20 #define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) 21 #define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) 22 23 #define MSI_DATA_LEVEL_SHIFT 14 24 #define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) 25 #define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) 26 27 #define MSI_DATA_TRIGGER_SHIFT 15 28 #define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) 29 #define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) 30 31 /* 32 * Shift/mask fields for APIC-based bus address 33 */ 34 35 #define MSI_TARGET_CPU_SHIFT 4 36 #define MSI_ADDR_HEADER 0xfee00000 37 38 #define MSI_ADDR_DESTID_MASK 0xfff0000f 39 #define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) 40 41 #define MSI_ADDR_DESTMODE_SHIFT 2 42 #define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) 43 #define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) 44 45 #define MSI_ADDR_REDIRECTION_SHIFT 3 46 #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) 47 #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) 48 49 static struct irq_chip ia64_msi_chip; 50 51 #ifdef CONFIG_SMP 52 static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) 53 { 54 struct msi_msg msg; 55 u32 addr, data; 56 int cpu = first_cpu(cpu_mask); 57 58 if (!cpu_online(cpu)) 59 return; 60 61 if (irq_prepare_move(irq, cpu)) 62 return; 63 64 read_msi_msg(irq, &msg); 65 66 addr = msg.address_lo; 67 addr &= MSI_ADDR_DESTID_MASK; 68 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); 69 msg.address_lo = addr; 70 71 data = msg.data; 72 data &= MSI_DATA_VECTOR_MASK; 73 data |= MSI_DATA_VECTOR(irq_to_vector(irq)); 74 msg.data = data; 75 76 write_msi_msg(irq, &msg); 77 irq_desc[irq].affinity = cpumask_of_cpu(cpu); 78 } 79 #endif /* CONFIG_SMP */ 80 81 int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 82 { 83 struct msi_msg msg; 84 unsigned long dest_phys_id; 85 int irq, vector; 86 cpumask_t mask; 87 88 irq = create_irq(); 89 if (irq < 0) 90 return irq; 91 92 set_irq_msi(irq, desc); 93 cpus_and(mask, irq_to_domain(irq), cpu_online_map); 94 dest_phys_id = cpu_physical_id(first_cpu(mask)); 95 vector = irq_to_vector(irq); 96 97 msg.address_hi = 0; 98 msg.address_lo = 99 MSI_ADDR_HEADER | 100 MSI_ADDR_DESTMODE_PHYS | 101 MSI_ADDR_REDIRECTION_CPU | 102 MSI_ADDR_DESTID_CPU(dest_phys_id); 103 104 msg.data = 105 MSI_DATA_TRIGGER_EDGE | 106 MSI_DATA_LEVEL_ASSERT | 107 MSI_DATA_DELIVERY_FIXED | 108 MSI_DATA_VECTOR(vector); 109 110 write_msi_msg(irq, &msg); 111 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); 112 113 return 0; 114 } 115 116 void ia64_teardown_msi_irq(unsigned int irq) 117 { 118 destroy_irq(irq); 119 } 120 121 static void ia64_ack_msi_irq(unsigned int irq) 122 { 123 irq_complete_move(irq); 124 move_native_irq(irq); 125 ia64_eoi(); 126 } 127 128 static int ia64_msi_retrigger_irq(unsigned int irq) 129 { 130 unsigned int vector = irq_to_vector(irq); 131 ia64_resend_irq(vector); 132 133 return 1; 134 } 135 136 /* 137 * Generic ops used on most IA64 platforms. 138 */ 139 static struct irq_chip ia64_msi_chip = { 140 .name = "PCI-MSI", 141 .mask = mask_msi_irq, 142 .unmask = unmask_msi_irq, 143 .ack = ia64_ack_msi_irq, 144 #ifdef CONFIG_SMP 145 .set_affinity = ia64_set_msi_irq_affinity, 146 #endif 147 .retrigger = ia64_msi_retrigger_irq, 148 }; 149 150 151 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 152 { 153 if (platform_setup_msi_irq) 154 return platform_setup_msi_irq(pdev, desc); 155 156 return ia64_setup_msi_irq(pdev, desc); 157 } 158 159 void arch_teardown_msi_irq(unsigned int irq) 160 { 161 if (platform_teardown_msi_irq) 162 return platform_teardown_msi_irq(irq); 163 164 return ia64_teardown_msi_irq(irq); 165 } 166 167 #ifdef CONFIG_DMAR 168 #ifdef CONFIG_SMP 169 static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) 170 { 171 struct irq_cfg *cfg = irq_cfg + irq; 172 struct msi_msg msg; 173 int cpu = first_cpu(mask); 174 175 176 if (!cpu_online(cpu)) 177 return; 178 179 if (irq_prepare_move(irq, cpu)) 180 return; 181 182 dmar_msi_read(irq, &msg); 183 184 msg.data &= ~MSI_DATA_VECTOR_MASK; 185 msg.data |= MSI_DATA_VECTOR(cfg->vector); 186 msg.address_lo &= ~MSI_ADDR_DESTID_MASK; 187 msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); 188 189 dmar_msi_write(irq, &msg); 190 irq_desc[irq].affinity = mask; 191 } 192 #endif /* CONFIG_SMP */ 193 194 struct irq_chip dmar_msi_type = { 195 .name = "DMAR_MSI", 196 .unmask = dmar_msi_unmask, 197 .mask = dmar_msi_mask, 198 .ack = ia64_ack_msi_irq, 199 #ifdef CONFIG_SMP 200 .set_affinity = dmar_msi_set_affinity, 201 #endif 202 .retrigger = ia64_msi_retrigger_irq, 203 }; 204 205 static int 206 msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 207 { 208 struct irq_cfg *cfg = irq_cfg + irq; 209 unsigned dest; 210 cpumask_t mask; 211 212 cpus_and(mask, irq_to_domain(irq), cpu_online_map); 213 dest = cpu_physical_id(first_cpu(mask)); 214 215 msg->address_hi = 0; 216 msg->address_lo = 217 MSI_ADDR_HEADER | 218 MSI_ADDR_DESTMODE_PHYS | 219 MSI_ADDR_REDIRECTION_CPU | 220 MSI_ADDR_DESTID_CPU(dest); 221 222 msg->data = 223 MSI_DATA_TRIGGER_EDGE | 224 MSI_DATA_LEVEL_ASSERT | 225 MSI_DATA_DELIVERY_FIXED | 226 MSI_DATA_VECTOR(cfg->vector); 227 return 0; 228 } 229 230 int arch_setup_dmar_msi(unsigned int irq) 231 { 232 int ret; 233 struct msi_msg msg; 234 235 ret = msi_compose_msg(NULL, irq, &msg); 236 if (ret < 0) 237 return ret; 238 dmar_msi_write(irq, &msg); 239 set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, 240 "edge"); 241 return 0; 242 } 243 #endif /* CONFIG_DMAR */ 244 245