@@ -835,6 +835,35 @@ static int spapr_phb_dma_init_window(sPAPRPHBState *sphb,
return 0;
}
+int spapr_phb_dma_remove_window(sPAPRPHBState *sphb,
+ sPAPRTCETable *tcet)
+{
+ spapr_tce_table_disable(tcet);
+
+ return 0;
+}
+
+int spapr_phb_dma_reset(sPAPRPHBState *sphb)
+{
+ int i;
+ sPAPRTCETable *tcet;
+ sPAPRPHBClass *spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
+
+ spc->dma_capabilities_update(sphb); /* Refresh @has_vfio status */
+
+ for (i = 0; i < SPAPR_PCI_DMA_MAX_WINDOWS; ++i) {
+ tcet = spapr_tce_find_by_liobn(SPAPR_PCI_LIOBN(sphb->index, i));
+ if (tcet) {
+ spapr_phb_dma_remove_window(sphb, tcet);
+ }
+ }
+
+ spc->dma_init_window(sphb, SPAPR_PCI_LIOBN(sphb->index, 0),
+ SPAPR_TCE_PAGE_SHIFT, sphb->dma32_window_size);
+
+ return 0;
+}
+
/* Macros to operate with address in OF binding to PCI */
#define b_x(x, p, l) (((x) & ((1<<(l))-1)) << (p))
#define b_n(x) b_x((x), 31, 1) /* 0 if relocatable */
@@ -1242,7 +1271,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
SysBusDevice *s = SYS_BUS_DEVICE(dev);
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
PCIHostState *phb = PCI_HOST_BRIDGE(s);
- sPAPRPHBClass *info = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(s);
char *namebuf;
int i;
PCIBus *bus;
@@ -1403,14 +1431,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
return;
}
- info->dma_capabilities_update(sphb);
- info->dma_init_window(sphb, sphb->dma_liobn, SPAPR_TCE_PAGE_SHIFT,
- sphb->dma32_window_size);
- tcet = spapr_tce_find_by_liobn(sphb->dma_liobn);
- if (!tcet) {
- error_setg(errp, "failed to create TCE table");
- return;
- }
memory_region_add_subregion(&sphb->iommu_root, 0,
spapr_tce_get_iommu(tcet));
@@ -1430,6 +1450,10 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
static void spapr_phb_reset(DeviceState *qdev)
{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
+
+ spapr_phb_dma_reset(sphb);
+
/* Reset the IOMMU state */
object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL);
}
@@ -73,6 +73,10 @@ static void spapr_phb_vfio_eeh_reenable(sPAPRPHBVFIOState *svphb)
static void spapr_phb_vfio_reset(DeviceState *qdev)
{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
+
+ spapr_phb_dma_reset(sphb);
+
/*
* The PE might be in frozen state. To reenable the EEH
* functionality on it will clean the frozen state, which
@@ -123,6 +123,8 @@ struct sPAPRPHBVFIOState {
#define SPAPR_PCI_DMA32_SIZE 0x40000000
+#define SPAPR_PCI_DMA_MAX_WINDOWS 1
+
static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
@@ -143,5 +145,8 @@ void spapr_pci_rtas_init(void);
sPAPRPHBState *spapr_pci_find_phb(sPAPRMachineState *spapr, uint64_t buid);
PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid,
uint32_t config_addr);
+int spapr_phb_dma_remove_window(sPAPRPHBState *sphb,
+ sPAPRTCETable *tcet);
+int spapr_phb_dma_reset(sPAPRPHBState *sphb);
#endif /* __HW_SPAPR_PCI_H__ */