aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2011-09-15 20:49:49 +0000
committerAlexander Graf <agraf@suse.de>2011-10-06 09:48:09 +0200
commite6c866d417d1a09536f489e66c21cf49b7ec60b6 (patch)
tree70fc7c03c5616c7446f6a866ce31e87a7520fb34
parent44427c401f7c0053db31f40a58a427e1ae3cd8c3 (diff)
pseries: Refactor spapr irq allocation
Paulo Bonzini changed the original spapr code, which manually assigned irq numbers for each virtual device, to allocate them automatically from the device initialization. That allowed spapr virtual devices to be constructed with -device, which is a good start. However, the way that patch worked doesn't extend nicely for the future when we want to support devices other than sPAPR VIO devices (e.g. virtio and PCI). This patch rearranges the irq allocation to be global across the sPAPR environment, so it can be used by other bus types as well. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
-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 {