Commit a307d594 authored by Alexey Kardashevskiy's avatar Alexey Kardashevskiy Committed by Alexander Graf
Browse files

pseries: Rework irq assignment to avoid carrying qemu_irqs around



Currently, the interfaces in the pseries machine code for assignment
and setup of interrupts pass around qemu_irq objects.  That was done
in an attempt not to be too closely linked to the specific XICS
interrupt controller.  However interactions with the device tree setup
made that attempt rather futile, and XICS is part of the PAPR spec
anyway, so this really just meant we had to carry both the qemu_irq
pointers and the XICS irq numbers around.

This mess will just get worse when we add upcoming PCI MSI support,
since that will require tracking a bunch more interrupt.  Therefore,
this patch reworks the spapr code to just use XICS irq numbers
(roughly equivalent to GSIs on x86) and only retrieve the qemu_irq
pointers from the XICS code when we need them (a trivial lookup).

This is a reworked and generalized version of an earlier spapr_pci
specific patch from Alexey Kardashevskiy.

Signed-off-by: default avatarAlexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
[agraf: fix checkpath warning]
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent c9f709d2
Loading
Loading
Loading
Loading
+7 −11
Original line number Diff line number Diff line
@@ -84,11 +84,9 @@

sPAPREnvironment *spapr;

qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
                            enum xics_irq_type type)
int spapr_allocate_irq(int hint, enum xics_irq_type type)
{
    uint32_t irq;
    qemu_irq qirq;
    int irq;

    if (hint) {
        irq = hint;
@@ -97,16 +95,14 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
        irq = spapr->next_irq++;
    }

    qirq = xics_assign_irq(spapr->icp, irq, type);
    if (!qirq) {
        return NULL;
    /* Configure irq type */
    if (!xics_get_qirq(spapr->icp, irq)) {
        return 0;
    }

    if (irq_num) {
        *irq_num = irq;
    }
    xics_set_irq_type(spapr->icp, irq, type);

    return qirq;
    return irq;
}

static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
+5 −6
Original line number Diff line number Diff line
@@ -289,17 +289,16 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
                             target_ulong *args);

qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
                            enum xics_irq_type type);
int spapr_allocate_irq(int hint, enum xics_irq_type type);

static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num)
static inline int spapr_allocate_msi(int hint)
{
    return spapr_allocate_irq(hint, irq_num, XICS_MSI);
    return spapr_allocate_irq(hint, XICS_MSI);
}

static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num)
static inline int spapr_allocate_lsi(int hint)
{
    return spapr_allocate_irq(hint, irq_num, XICS_LSI);
    return spapr_allocate_irq(hint, XICS_LSI);
}

static inline uint32_t rtas_ld(target_ulong phys, int n)
+1 −1
Original line number Diff line number Diff line
@@ -169,7 +169,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
    }

    if (sdev->signal_state & 1) {
        qemu_irq_pulse(sdev->qirq);
        qemu_irq_pulse(spapr_vio_qirq(sdev));
    }

    return size;
+6 −8
Original line number Diff line number Diff line
@@ -223,7 +223,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
     */
    sPAPRPHBState *phb = opaque;

    qemu_set_irq(phb->lsi_table[irq_num].qirq, level);
    qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
}

static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
@@ -329,16 +329,14 @@ static int spapr_phb_init(SysBusDevice *s)

    /* Initialize the LSI table */
    for (i = 0; i < PCI_NUM_PINS; i++) {
        qemu_irq qirq;
        uint32_t num;
        uint32_t irq;

        qirq = spapr_allocate_lsi(0, &num);
        if (!qirq) {
        irq = spapr_allocate_lsi(0);
        if (!irq) {
            return -1;
        }

        phb->lsi_table[i].dt_irq = num;
        phb->lsi_table[i].qirq = qirq;
        phb->lsi_table[i].irq = irq;
    }

    return 0;
@@ -477,7 +475,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
            irqmap[2] = 0;
            irqmap[3] = cpu_to_be32(j+1);
            irqmap[4] = cpu_to_be32(xics_phandle);
            irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].dt_irq);
            irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq);
            irqmap[6] = cpu_to_be32(0x8);
        }
    }
+6 −2
Original line number Diff line number Diff line
@@ -40,13 +40,17 @@ typedef struct sPAPRPHBState {
    DMAContext *dma;

    struct {
        uint32_t dt_irq;
        qemu_irq qirq;
        uint32_t irq;
    } lsi_table[PCI_NUM_PINS];

    QLIST_ENTRY(sPAPRPHBState) list;
} sPAPRPHBState;

static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
{
    return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq);
}

#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
#define SPAPR_PCI_IO_WIN_SIZE        0x10000

Loading