diff options
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 139 |
1 files changed, 80 insertions, 59 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index a7052fafdd43..2fbb9d6a37ed 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -1255,72 +1255,95 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg, | |||
| 1255 | fasteoi ? "fasteoi" : "edge"); | 1255 | fasteoi ? "fasteoi" : "edge"); |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | static int setup_ioapic_entry(int apic_id, int irq, | 1258 | |
| 1259 | struct IO_APIC_route_entry *entry, | 1259 | static int setup_ir_ioapic_entry(int irq, |
| 1260 | unsigned int destination, int trigger, | 1260 | struct IR_IO_APIC_route_entry *entry, |
| 1261 | int polarity, int vector, int pin) | 1261 | unsigned int destination, int vector, |
| 1262 | struct io_apic_irq_attr *attr) | ||
| 1262 | { | 1263 | { |
| 1263 | /* | 1264 | int index; |
| 1264 | * add it to the IO-APIC irq-routing table: | 1265 | struct irte irte; |
| 1265 | */ | 1266 | int apic_id = mpc_ioapic_id(attr->ioapic); |
| 1266 | memset(entry,0,sizeof(*entry)); | 1267 | struct intel_iommu *iommu = map_ioapic_to_ir(apic_id); |
| 1267 | 1268 | ||
| 1268 | if (intr_remapping_enabled) { | 1269 | if (!iommu) { |
| 1269 | struct intel_iommu *iommu = map_ioapic_to_ir(apic_id); | 1270 | pr_warn("No mapping iommu for ioapic %d\n", apic_id); |
| 1270 | struct irte irte; | 1271 | return -ENODEV; |
| 1271 | struct IR_IO_APIC_route_entry *ir_entry = | 1272 | } |
| 1272 | (struct IR_IO_APIC_route_entry *) entry; | ||
| 1273 | int index; | ||
| 1274 | 1273 | ||
| 1275 | if (!iommu) | 1274 | index = alloc_irte(iommu, irq, 1); |
| 1276 | panic("No mapping iommu for ioapic %d\n", apic_id); | 1275 | if (index < 0) { |
| 1276 | pr_warn("Failed to allocate IRTE for ioapic %d\n", apic_id); | ||
| 1277 | return -ENOMEM; | ||
| 1278 | } | ||
| 1277 | 1279 | ||
| 1278 | index = alloc_irte(iommu, irq, 1); | 1280 | prepare_irte(&irte, vector, destination); |
| 1279 | if (index < 0) | ||
| 1280 | panic("Failed to allocate IRTE for ioapic %d\n", apic_id); | ||
| 1281 | 1281 | ||
| 1282 | prepare_irte(&irte, vector, destination); | 1282 | /* Set source-id of interrupt request */ |
| 1283 | set_ioapic_sid(&irte, apic_id); | ||
| 1283 | 1284 | ||
| 1284 | /* Set source-id of interrupt request */ | 1285 | modify_irte(irq, &irte); |
| 1285 | set_ioapic_sid(&irte, apic_id); | ||
| 1286 | 1286 | ||
| 1287 | modify_irte(irq, &irte); | 1287 | apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " |
| 1288 | "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " | ||
| 1289 | "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " | ||
| 1290 | "Avail:%X Vector:%02X Dest:%08X " | ||
| 1291 | "SID:%04X SQ:%X SVT:%X)\n", | ||
| 1292 | apic_id, irte.present, irte.fpd, irte.dst_mode, | ||
| 1293 | irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, | ||
| 1294 | irte.avail, irte.vector, irte.dest_id, | ||
| 1295 | irte.sid, irte.sq, irte.svt); | ||
| 1296 | |||
| 1297 | memset(entry, 0, sizeof(*entry)); | ||
| 1298 | |||
| 1299 | entry->index2 = (index >> 15) & 0x1; | ||
| 1300 | entry->zero = 0; | ||
| 1301 | entry->format = 1; | ||
| 1302 | entry->index = (index & 0x7fff); | ||
| 1303 | /* | ||
| 1304 | * IO-APIC RTE will be configured with virtual vector. | ||
| 1305 | * irq handler will do the explicit EOI to the io-apic. | ||
| 1306 | */ | ||
| 1307 | entry->vector = attr->ioapic_pin; | ||
| 1308 | entry->mask = 0; /* enable IRQ */ | ||
| 1309 | entry->trigger = attr->trigger; | ||
| 1310 | entry->polarity = attr->polarity; | ||
| 1288 | 1311 | ||
| 1289 | ir_entry->index2 = (index >> 15) & 0x1; | 1312 | /* Mask level triggered irqs. |
| 1290 | ir_entry->zero = 0; | 1313 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. |
| 1291 | ir_entry->format = 1; | 1314 | */ |
| 1292 | ir_entry->index = (index & 0x7fff); | 1315 | if (attr->trigger) |
| 1293 | /* | 1316 | entry->mask = 1; |
| 1294 | * IO-APIC RTE will be configured with virtual vector. | ||
| 1295 | * irq handler will do the explicit EOI to the io-apic. | ||
| 1296 | */ | ||
| 1297 | ir_entry->vector = pin; | ||
| 1298 | |||
| 1299 | apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " | ||
| 1300 | "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " | ||
| 1301 | "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " | ||
| 1302 | "Avail:%X Vector:%02X Dest:%08X " | ||
| 1303 | "SID:%04X SQ:%X SVT:%X)\n", | ||
| 1304 | apic_id, irte.present, irte.fpd, irte.dst_mode, | ||
| 1305 | irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, | ||
| 1306 | irte.avail, irte.vector, irte.dest_id, | ||
| 1307 | irte.sid, irte.sq, irte.svt); | ||
| 1308 | } else { | ||
| 1309 | entry->delivery_mode = apic->irq_delivery_mode; | ||
| 1310 | entry->dest_mode = apic->irq_dest_mode; | ||
| 1311 | entry->dest = destination; | ||
| 1312 | entry->vector = vector; | ||
| 1313 | } | ||
| 1314 | 1317 | ||
| 1315 | entry->mask = 0; /* enable IRQ */ | 1318 | return 0; |
| 1316 | entry->trigger = trigger; | 1319 | } |
| 1317 | entry->polarity = polarity; | ||
| 1318 | 1320 | ||
| 1319 | /* Mask level triggered irqs. | 1321 | static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, |
| 1322 | unsigned int destination, int vector, | ||
| 1323 | struct io_apic_irq_attr *attr) | ||
| 1324 | { | ||
| 1325 | if (intr_remapping_enabled) | ||
| 1326 | return setup_ir_ioapic_entry(irq, | ||
| 1327 | (struct IR_IO_APIC_route_entry *)entry, | ||
| 1328 | destination, vector, attr); | ||
| 1329 | |||
| 1330 | memset(entry, 0, sizeof(*entry)); | ||
| 1331 | |||
| 1332 | entry->delivery_mode = apic->irq_delivery_mode; | ||
| 1333 | entry->dest_mode = apic->irq_dest_mode; | ||
| 1334 | entry->dest = destination; | ||
| 1335 | entry->vector = vector; | ||
| 1336 | entry->mask = 0; /* enable IRQ */ | ||
| 1337 | entry->trigger = attr->trigger; | ||
| 1338 | entry->polarity = attr->polarity; | ||
| 1339 | |||
| 1340 | /* | ||
| 1341 | * Mask level triggered irqs. | ||
| 1320 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. | 1342 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. |
| 1321 | */ | 1343 | */ |
| 1322 | if (trigger) | 1344 | if (attr->trigger) |
| 1323 | entry->mask = 1; | 1345 | entry->mask = 1; |
| 1346 | |||
| 1324 | return 0; | 1347 | return 0; |
| 1325 | } | 1348 | } |
| 1326 | 1349 | ||
| @@ -1351,13 +1374,11 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg, | |||
| 1351 | attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin, | 1374 | attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin, |
| 1352 | cfg->vector, irq, attr->trigger, attr->polarity, dest); | 1375 | cfg->vector, irq, attr->trigger, attr->polarity, dest); |
| 1353 | 1376 | ||
| 1354 | 1377 | if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) { | |
| 1355 | if (setup_ioapic_entry(mpc_ioapic_id(attr->ioapic), irq, &entry, | 1378 | pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n", |
| 1356 | dest, attr->trigger, attr->polarity, cfg->vector, | 1379 | mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); |
| 1357 | attr->ioapic_pin)) { | ||
| 1358 | printk("Failed to setup ioapic entry for ioapic %d, pin %d\n", | ||
| 1359 | mpc_ioapic_id(attr->ioapic), attr->ioapic_pin); | ||
| 1360 | __clear_irq_vector(irq, cfg); | 1380 | __clear_irq_vector(irq, cfg); |
| 1381 | |||
| 1361 | return; | 1382 | return; |
| 1362 | } | 1383 | } |
| 1363 | 1384 | ||
