/* Global interrupt distribution server is specified in the last *entryof"ibm,ppc-interrupt-gserver#s"property.Getthelast *entryfomthispropertyforcurrentbootcpuidanduseitas *defaultdistributionserver
*/ for (j = 0; j < i; j += 2) { if (be32_to_cpu(ireg[j]) == hcpuid) {
xics_default_distrib_server = be32_to_cpu(ireg[j+1]); break;
}
}
pr_devel("xics: xics_default_distrib_server = 0x%x\n",
xics_default_distrib_server);
of_node_put(np);
}
/* GIQ stuff, currently only supported on RTAS setups, will have *tobesortedproperlyforbaremetal
*/ void xics_set_cpu_giq(unsignedint gserver, unsignedint join)
{ #ifdef CONFIG_PPC_RTAS int index; int status;
if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL)) return;
index = (1UL << xics_interrupt_server_size) - 1 - gserver;
status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join);
/* We can't set affinity on ISA interrupts */ if (virq < NR_IRQS_LEGACY) continue; /* We only need to migrate enabled IRQS */ if (!desc->action) continue; /* We need a mapping in the XICS IRQ domain */
irqd = irq_domain_get_irq_data(xics_host, virq); if (!irqd) continue;
irq = irqd_to_hwirq(irqd); /* We need to get IPIs still. */ if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) continue;
chip = irq_desc_get_chip(desc); if (!chip || !chip->irq_set_affinity) continue;
raw_spin_lock_irqsave(&desc->lock, flags);
/* Locate interrupt server */
server = xics_ics->get_server(xics_ics, irq); if (server < 0) {
pr_err("%s: Can't find server for irq %d/%x\n",
__func__, virq, irq); goto unlock;
}
/* We only support delivery to all cpus or to one cpu. *Theirqhastobemigratedonlyinthesinglecpu *case.
*/ if (server != hw_cpu) goto unlock;
/* This is expected during cpu offline. */ if (cpu_online(cpu))
pr_warn("IRQ %u affinity broken off cpu %u\n",
virq, cpu);
/* Reset affinity to all cpus */
raw_spin_unlock_irqrestore(&desc->lock, flags);
irq_set_affinity(virq, cpu_all_mask); continue;
unlock:
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
/* Allow "sufficient" time to drop any inflight IRQ's */
mdelay(5);
/* Don't call into ICS for IPIs */ if (hwirq == XICS_IPI) {
irq_set_chip_and_handler(virq, &xics_ipi_chip,
handle_percpu_irq); return0;
}
if (WARN_ON(!xics_ics)) return -EINVAL;
if (xics_ics->check(xics_ics, hwirq)) return -EINVAL;
/* Let the ICS be the chip data for the XICS domain. For ICS native */
irq_domain_set_info(domain, virq, hwirq, xics_ics->chip,
xics_ics, handle_fasteoi_irq, NULL, NULL);
/* We fetch the interrupt server size from the first ICS node *wefindifany
*/
np = of_find_compatible_node(NULL, NULL, "ibm,ppc-xics"); if (!np) return;
isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); if (isize)
xics_interrupt_server_size = be32_to_cpu(*isize);
of_node_put(np);
}
void __init xics_init(void)
{ int rc = -1;
/* Fist locate ICP */ if (firmware_has_feature(FW_FEATURE_LPAR))
rc = icp_hv_init(); if (rc < 0) {
rc = icp_native_init(); if (rc == -ENODEV)
rc = icp_opal_init();
} if (rc < 0) {
pr_warn("XICS: Cannot find a Presentation Controller !\n"); return;
}
/* Copy get_irq callback over to ppc_md */
ppc_md.get_irq = icp_ops->get_irq;
/* Patch up IPI chip EOI */
xics_ipi_chip.irq_eoi = icp_ops->eoi;
/* Now locate ICS */
rc = ics_rtas_init(); if (rc < 0)
rc = ics_opal_init(); if (rc < 0)
rc = ics_native_init(); if (rc < 0)
pr_warn("XICS: Cannot find a Source Controller !\n");
/* Initialize common bits */
xics_get_server_size();
xics_update_irq_servers();
rc = xics_allocate_domain(); if (rc < 0)
pr_err("XICS: Failed to create IRQ domain");
xics_setup_cpu();
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.