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 void 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; 24 25 if (irq_prepare_move(irq, cpu)) 26 return; 27 28 read_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 #endif /* CONFIG_SMP */ 44 45 int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 46 { 47 struct msi_msg msg; 48 unsigned long dest_phys_id; 49 int irq, vector; 50 cpumask_t mask; 51 52 irq = create_irq(); 53 if (irq < 0) 54 return irq; 55 56 set_irq_msi(irq, desc); 57 cpus_and(mask, irq_to_domain(irq), cpu_online_map); 58 dest_phys_id = cpu_physical_id(first_cpu(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 write_msi_msg(irq, &msg); 75 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); 76 77 return 0; 78 } 79 80 void ia64_teardown_msi_irq(unsigned int irq) 81 { 82 destroy_irq(irq); 83 } 84 85 static void ia64_ack_msi_irq(unsigned int irq) 86 { 87 irq_complete_move(irq); 88 move_native_irq(irq); 89 ia64_eoi(); 90 } 91 92 static int ia64_msi_retrigger_irq(unsigned int irq) 93 { 94 unsigned int vector = irq_to_vector(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 .mask = mask_msi_irq, 106 .unmask = unmask_msi_irq, 107 .ack = ia64_ack_msi_irq, 108 #ifdef CONFIG_SMP 109 .set_affinity = ia64_set_msi_irq_affinity, 110 #endif 111 .retrigger = ia64_msi_retrigger_irq, 112 }; 113 114 115 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 116 { 117 if (platform_setup_msi_irq) 118 return platform_setup_msi_irq(pdev, desc); 119 120 return ia64_setup_msi_irq(pdev, desc); 121 } 122 123 void arch_teardown_msi_irq(unsigned int irq) 124 { 125 if (platform_teardown_msi_irq) 126 return platform_teardown_msi_irq(irq); 127 128 return ia64_teardown_msi_irq(irq); 129 } 130 131 #ifdef CONFIG_DMAR 132 #ifdef CONFIG_SMP 133 static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask) 134 { 135 struct irq_cfg *cfg = irq_cfg + irq; 136 struct msi_msg msg; 137 int cpu = cpumask_first(mask); 138 139 if (!cpu_online(cpu)) 140 return; 141 142 if (irq_prepare_move(irq, cpu)) 143 return; 144 145 dmar_msi_read(irq, &msg); 146 147 msg.data &= ~MSI_DATA_VECTOR_MASK; 148 msg.data |= MSI_DATA_VECTOR(cfg->vector); 149 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; 150 msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu)); 151 152 dmar_msi_write(irq, &msg); 153 cpumask_copy(irq_desc[irq].affinity, mask); 154 } 155 #endif /* CONFIG_SMP */ 156 157 struct irq_chip dmar_msi_type = { 158 .name = "DMAR_MSI", 159 .unmask = dmar_msi_unmask, 160 .mask = dmar_msi_mask, 161 .ack = ia64_ack_msi_irq, 162 #ifdef CONFIG_SMP 163 .set_affinity = dmar_msi_set_affinity, 164 #endif 165 .retrigger = ia64_msi_retrigger_irq, 166 }; 167 168 static int 169 msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 170 { 171 struct irq_cfg *cfg = irq_cfg + irq; 172 unsigned dest; 173 cpumask_t mask; 174 175 cpus_and(mask, irq_to_domain(irq), cpu_online_map); 176 dest = cpu_physical_id(first_cpu(mask)); 177 178 msg->address_hi = 0; 179 msg->address_lo = 180 MSI_ADDR_HEADER | 181 MSI_ADDR_DEST_MODE_PHYS | 182 MSI_ADDR_REDIRECTION_CPU | 183 MSI_ADDR_DEST_ID_CPU(dest); 184 185 msg->data = 186 MSI_DATA_TRIGGER_EDGE | 187 MSI_DATA_LEVEL_ASSERT | 188 MSI_DATA_DELIVERY_FIXED | 189 MSI_DATA_VECTOR(cfg->vector); 190 return 0; 191 } 192 193 int arch_setup_dmar_msi(unsigned int irq) 194 { 195 int ret; 196 struct msi_msg msg; 197 198 ret = msi_compose_msg(NULL, irq, &msg); 199 if (ret < 0) 200 return ret; 201 dmar_msi_write(irq, &msg); 202 set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, 203 "edge"); 204 return 0; 205 } 206 #endif /* CONFIG_DMAR */ 207 208