diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2014-05-27 15:36:33 +1000 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-06-16 13:24:39 +0200 |
commit | e28c16f61feefa197e04e83662f32bfc1d607723 (patch) | |
tree | 47f362c4ae61db1fa995ab809e04262a3713a877 /hw/ppc | |
parent | cca7fad5765251fece44cd230156a101867522dd (diff) |
spapr_pci: Allow multiple TCE tables per PHB
At the moment sPAPRPHBState contains a @tcet pointer to the only
TCE table. However sPAPR spec allows having more than one DMA window.
Since the TCE object is already a child of SPAPR PHB object, there is
no need to keep an additional pointer to it in sPAPRPHBState so remove it.
This changes the way sPAPRPHBState::reset performs reset of sPAPRTCETable
objects.
This changes the default DMA window properties calculation.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/spapr_pci.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index ba020320eb..bc23614956 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -653,11 +653,13 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp) { + sPAPRTCETable *tcet; + sphb->dma_window_start = 0; sphb->dma_window_size = 0x40000000; - sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn, - sphb->dma_window_size); - if (!sphb->tcet) { + tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn, + sphb->dma_window_size); + if (!tcet) { error_setg(errp, "Unable to create TCE table for %s", sphb->dtbusname); return ; @@ -665,16 +667,24 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp) /* Register default 32bit DMA window */ memory_region_add_subregion(&sphb->iommu_root, 0, - spapr_tce_get_iommu(sphb->tcet)); + spapr_tce_get_iommu(tcet)); } -static void spapr_phb_reset(DeviceState *qdev) +static int spapr_phb_children_reset(Object *child, void *opaque) { - SysBusDevice *s = SYS_BUS_DEVICE(qdev); - sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); + DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE); + + if (dev) { + device_reset(dev); + } + return 0; +} + +static void spapr_phb_reset(DeviceState *qdev) +{ /* Reset the IOMMU state */ - device_reset(DEVICE(sphb->tcet)); + object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL); } static Property spapr_phb_properties[] = { @@ -788,6 +798,29 @@ PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index) #define b_fff(x) b_x((x), 8, 3) /* function number */ #define b_rrrrrrrr(x) b_x((x), 0, 8) /* register number */ +typedef struct sPAPRTCEDT { + void *fdt; + int node_off; +} sPAPRTCEDT; + +static int spapr_phb_children_dt(Object *child, void *opaque) +{ + sPAPRTCEDT *p = opaque; + sPAPRTCETable *tcet; + + tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE); + if (!tcet) { + return 0; + } + + spapr_dma_dt(p->fdt, p->node_off, "ibm,dma-window", + tcet->liobn, 0, + tcet->window_size); + /* Stop after the first window */ + + return 1; +} + int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt) @@ -867,9 +900,8 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map, sizeof(interrupt_map))); - spapr_dma_dt(fdt, bus_off, "ibm,dma-window", - phb->dma_liobn, phb->dma_window_start, - phb->dma_window_size); + object_child_foreach(OBJECT(phb), spapr_phb_children_dt, + &((sPAPRTCEDT){ .fdt = fdt, .node_off = bus_off })); return 0; } |