aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hw/spapr.c25
-rw-r--r--hw/spapr.h7
-rw-r--r--hw/spapr_vio.c9
-rw-r--r--hw/spapr_vio.h1
4 files changed, 31 insertions, 11 deletions
diff --git a/hw/spapr.c b/hw/spapr.c
index deb4ae541..b1189755d 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -61,6 +61,30 @@
sPAPREnvironment *spapr;
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
+{
+ uint32_t irq;
+ qemu_irq qirq;
+
+ if (hint) {
+ irq = hint;
+ /* FIXME: we should probably check for collisions somehow */
+ } else {
+ irq = spapr->next_irq++;
+ }
+
+ qirq = xics_find_qirq(spapr->icp, irq);
+ if (!qirq) {
+ return NULL;
+ }
+
+ if (irq_num) {
+ *irq_num = irq;
+ }
+
+ return qirq;
+}
+
static void *spapr_create_fdt_skel(const char *cpu_model,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
@@ -372,6 +396,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
/* Set up Interrupt Controller */
spapr->icp = xics_system_init(XICS_IRQS);
+ spapr->next_irq = 16;
/* Set up VIO bus */
spapr->vio_bus = spapr_vio_bus_init();
diff --git a/hw/spapr.h b/hw/spapr.h
index 3d21b7a1c..ec910de5b 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -17,6 +17,7 @@ typedef struct sPAPREnvironment {
long rtas_size;
void *fdt_skel;
target_ulong entry_point;
+ int next_irq;
} sPAPREnvironment;
#define H_SUCCESS 0
@@ -281,11 +282,7 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
target_ulong *args);
-static inline qemu_irq spapr_find_qirq(sPAPREnvironment *spapr,
- int irq_num)
-{
- return xics_find_qirq(spapr->icp, irq_num);
-}
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num);
static inline uint32_t rtas_ld(target_ulong phys, int n)
{
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 0546ccb04..35818e18f 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -600,7 +600,6 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
{
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
- VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
char *id;
if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) {
@@ -608,10 +607,11 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
}
dev->qdev.id = id;
- if (!dev->vio_irq_num) {
- dev->vio_irq_num = bus->irq++;
+
+ dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
+ if (!dev->qirq) {
+ return -1;
}
- dev->qirq = spapr_find_qirq(spapr, dev->vio_irq_num);
rtce_init(dev);
@@ -666,7 +666,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
- bus->irq = 16;
/* hcall-vio */
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 7eb536765..4fe5f742c 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -67,7 +67,6 @@ typedef struct VIOsPAPRDevice {
typedef struct VIOsPAPRBus {
BusState bus;
- int irq;
} VIOsPAPRBus;
typedef struct {