aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr.c
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2018-06-18 19:34:00 +0200
committerDavid Gibson <david@gibson.dropbear.id.au>2018-06-21 21:22:53 +1000
commit4fe75a8ccd8005f8d0322c5b85ebee6243b2e753 (patch)
tree0c92f857ae9de3c5d01b04c15d227875bbeb46ed /hw/ppc/spapr.c
parent24c6863c7b61efcfe4a0f0916ed4e8b797c8d281 (diff)
downloadqemu-4fe75a8ccd8005f8d0322c5b85ebee6243b2e753.zip
qemu-4fe75a8ccd8005f8d0322c5b85ebee6243b2e753.tar.gz
qemu-4fe75a8ccd8005f8d0322c5b85ebee6243b2e753.tar.bz2
spapr: split the IRQ allocation sequence
Today, when a device requests for IRQ number in a sPAPR machine, the spapr_irq_alloc() routine first scans the ICSState status array to find an empty slot and then performs the assignement of the selected numbers. Split this sequence in two distinct routines : spapr_irq_find() for lookups and spapr_irq_claim() for claiming the IRQ numbers. This will ease the introduction of a static layout of IRQ numbers. Signed-off-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r--hw/ppc/spapr.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4a0b679..b7705c3 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3816,6 +3816,36 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
return -1;
}
+int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
+{
+ ICSState *ics = spapr->ics;
+ int first = -1;
+
+ assert(ics);
+
+ /*
+ * MSIMesage::data is used for storing VIRQ so
+ * it has to be aligned to num to support multiple
+ * MSI vectors. MSI-X is not affected by this.
+ * The hint is used for the first IRQ, the rest should
+ * be allocated continuously.
+ */
+ if (align) {
+ assert((num == 1) || (num == 2) || (num == 4) ||
+ (num == 8) || (num == 16) || (num == 32));
+ first = ics_find_free_block(ics, num, num);
+ } else {
+ first = ics_find_free_block(ics, num, 1);
+ }
+
+ if (first < 0) {
+ error_setg(errp, "can't find a free %d-IRQ block", num);
+ return -1;
+ }
+
+ return first + ics->offset;
+}
+
/*
* Allocate the IRQ number and set the IRQ type, LSI or MSI
*/
@@ -3894,6 +3924,26 @@ int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi,
return first;
}
+int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
+{
+ ICSState *ics = spapr->ics;
+
+ assert(ics);
+
+ if (!ics_valid_irq(ics, irq)) {
+ error_setg(errp, "IRQ %d is invalid", irq);
+ return -1;
+ }
+
+ if (!ICS_IRQ_FREE(ics, irq - ics->offset)) {
+ error_setg(errp, "IRQ %d is not free", irq);
+ return -1;
+ }
+
+ spapr_irq_set_lsi(spapr, irq, lsi);
+ return 0;
+}
+
void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
{
ICSState *ics = spapr->ics;