@@ -562,6 +562,33 @@ static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg,
PCI_VENDOR_ID, 4, &temp) || \
temp == 0xffffffff) {} else
+static void vmd_restore_domain(void *data)
+{
+ struct vmd_dev *vmd = data;
+ int root_port;
+ u32 temp, iobase;
+
+ /*
+ * It shouldn't be possible for the Root Port layout to change
+ * dynamically (outside of BIOS), however there is no harm in writing
+ * the persistent data back to all enabled Root Ports. PCI resource
+ * assignment will discard any modifications on the next VMD domain bus
+ * scan following VMD reset/probe.
+ */
+ for_each_vmd_root_port(vmd, root_port, temp) {
+ if (vmd_cfg_read(vmd, 0, PCI_DEVFN(root_port, 0),
+ PCI_IO_BASE, 2, &iobase))
+ return;
+
+ iobase &= ~((0xf << 4) | (0x3 << 14));
+ iobase |= vmd->socket_nr << 4 | vmd->instance_nr << 14;
+
+ if (vmd_cfg_write(vmd, 0, PCI_DEVFN(root_port, 0),
+ PCI_IO_BASE, 2, iobase))
+ return;
+ }
+}
+
static int vmd_parse_domain(struct vmd_dev *vmd)
{
int root_port, ret;
@@ -579,6 +606,11 @@ static int vmd_parse_domain(struct vmd_dev *vmd)
vmd->socket_nr = (iobase >> 4) & 0xf;
vmd->instance_nr = (iobase >> 14) & 0x3;
+ ret = devm_add_action_or_reset(&vmd->dev->dev,
+ vmd_restore_domain, vmd);
+ if (ret)
+ return ret;
+
/* First available will be used */
break;
}