aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/spapr.c7
-rw-r--r--hw/spapr_llan.c5
-rw-r--r--hw/spapr_vio.c54
-rw-r--r--hw/spapr_vio.h13
-rw-r--r--hw/spapr_vscsi.c5
-rw-r--r--hw/spapr_vty.c5
6 files changed, 49 insertions, 40 deletions
diff --git a/hw/spapr.c b/hw/spapr.c
index bfaf260d54..cca20f9a51 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -631,8 +631,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
for (i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
- spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i,
- serial_hds[i]);
+ spapr_vty_create(spapr->vio_bus, serial_hds[i]);
}
}
@@ -650,14 +649,14 @@ static void ppc_spapr_init(ram_addr_t ram_size,
}
if (strcmp(nd->model, "ibmveth") == 0) {
- spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd);
+ spapr_vlan_create(spapr->vio_bus, nd);
} else {
pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
}
}
for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
- spapr_vscsi_create(spapr->vio_bus, 0x2000 + i);
+ spapr_vscsi_create(spapr->vio_bus);
}
if (rma_size < (MIN_RMA_SLOF << 20)) {
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index e18d2eb901..8313043652 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -204,12 +204,11 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
return 0;
}
-void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd)
+void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
{
DeviceState *dev;
dev = qdev_create(&bus->bus, "spapr-vlan");
- qdev_prop_set_uint32(dev, "reg", reg);
qdev_set_nic_properties(dev, nd);
@@ -480,7 +479,7 @@ static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr,
}
static Property spapr_vlan_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x10000000),
DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index fccf48bd67..315ab8091c 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -620,28 +620,22 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
rtas_st(rets, 0, 0);
}
-static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
+static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
{
- VIOsPAPRDevice *other_sdev;
+ VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
DeviceState *qdev;
- VIOsPAPRBus *sbus;
-
- sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);
+ VIOsPAPRDevice *other;
/*
- * Check two device aren't given clashing addresses by the user (or some
- * other mechanism). We have to open code this because we have to check
- * for matches with devices other than us.
+ * Check for a device other than the given one which is already
+ * using the requested address. We have to open code this because
+ * the given dev might already be in the list.
*/
- QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) {
- other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+ QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
+ other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
- if (other_sdev != sdev && other_sdev->reg == sdev->reg) {
- fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
- object_get_typename(OBJECT(sdev)),
- object_get_typename(OBJECT(qdev)),
- sdev->reg);
- return -EEXIST;
+ if (other != dev && other->reg == dev->reg) {
+ return other;
}
}
@@ -667,11 +661,30 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
char *id;
- int ret;
- ret = spapr_vio_check_reg(dev);
- if (ret) {
- return ret;
+ if (dev->reg != -1) {
+ /*
+ * Explicitly assigned address, just verify that no-one else
+ * is using it. other mechanism). We have to open code this
+ * rather than using spapr_vio_find_by_reg() because sdev
+ * itself is already in the list.
+ */
+ VIOsPAPRDevice *other = reg_conflict(dev);
+
+ if (other) {
+ fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
+ object_get_typename(OBJECT(qdev)),
+ object_get_typename(OBJECT(&other->qdev)),
+ dev->reg);
+ return -1;
+ }
+ } else {
+ /* Need to assign an address */
+ VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
+
+ do {
+ dev->reg = bus->next_reg++;
+ } while (reg_conflict(dev));
}
/* Don't overwrite ids assigned on the command line */
@@ -731,6 +744,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
+ bus->next_reg = 0x1000;
/* hcall-vio */
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 10ab3594c0..87816e456d 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -32,8 +32,6 @@ enum VIOsPAPR_TCEAccess {
SPAPR_TCE_RW = 3,
};
-#define SPAPR_VTY_BASE_ADDRESS 0x30000000
-
#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
#define VIO_SPAPR_DEVICE(obj) \
OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
@@ -82,13 +80,14 @@ struct VIOsPAPRDevice {
VIOsPAPR_CRQ crq;
};
-#define DEFINE_SPAPR_PROPERTIES(type, field, default_reg, default_dma_window) \
- DEFINE_PROP_UINT32("reg", type, field.reg, default_reg), \
+#define DEFINE_SPAPR_PROPERTIES(type, field, default_dma_window) \
+ DEFINE_PROP_UINT32("reg", type, field.reg, -1), \
DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \
default_dma_window)
struct VIOsPAPRBus {
BusState bus;
+ uint32_t next_reg;
int (*init)(VIOsPAPRDevice *dev);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
};
@@ -119,9 +118,9 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
-void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
-void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
-void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
+void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev);
+void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd);
+void spapr_vscsi_create(VIOsPAPRBus *bus);
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 538e0b7938..037867ab4f 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -918,12 +918,11 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
return 0;
}
-void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg)
+void spapr_vscsi_create(VIOsPAPRBus *bus)
{
DeviceState *dev;
dev = qdev_create(&bus->bus, "spapr-vscsi");
- qdev_prop_set_uint32(dev, "reg", reg);
qdev_init_nofail(dev);
}
@@ -946,7 +945,7 @@ static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
}
static Property spapr_vscsi_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000),
+ DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x10000000),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index a30c040b97..c9674f36a6 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -123,18 +123,17 @@ static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
-void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
+void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev)
{
DeviceState *dev;
dev = qdev_create(&bus->bus, "spapr-vty");
- qdev_prop_set_uint32(dev, "reg", reg);
qdev_prop_set_chr(dev, "chardev", chardev);
qdev_init_nofail(dev);
}
static Property spapr_vty_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0),
DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
DEFINE_PROP_END_OF_LIST(),
};