PCI: allow assignment of memory resources with a specified alignment

This patch allows memory resources to be assigned with a specified
alignment at boot-time or run-time. The patch is useful when we use PCI
pass-through, because page-aligned memory resources are required to
securely share PCI resources with guest drivers.

If you want to assign the resource at boot time, please set
"pci=resource_alignment=" boot parameter.

This is format of "pci=resource_alignment=" boot parameter:

        [<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
                Specifies alignment and device to reassign
                aligned memory resources.
                If <order of align> is not specified, PAGE_SIZE is
                used as alignment.
                PCI-PCI bridge can be specified, if resource
                windows need to be expanded.

This is example:

        pci=resource_alignment=20@07:00.0;18@0f:00.0;00:1d.7

If you want to assign the resource at run-time, please set
"/sys/bus/pci/resource_alignment" file, and hot-remove the device and
hot-add the device.  For this purpose, fakephp or PCI hotplug interfaces
can be used.

The format of "/sys/bus/pci/resource_alignment" file is the same with
boot parameter. You can use "," instead of ";".

For example:

        # cd /sys/bus/pci
        # echo -n 20@12:00.0 > resource_alignment
        # echo 1 > devices/0000:12:00.0/remove
        # echo 1 > rescan

Reviewed-by: Alex Chiang <achiang@hp.com>
Reviewed-by: Yu Zhao <yu.zhao@intel.com>
Signed-off-by: Yuji Shimada <shimada-yxb@necst.nec.co.jp>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 32e8d88..3039fcb 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -120,6 +120,21 @@
 	return err;
 }
 
+#ifdef CONFIG_PCI_QUIRKS
+void pci_disable_bridge_window(struct pci_dev *dev)
+{
+	dev_dbg(&dev->dev, "Disabling bridge window.\n");
+
+	/* MMIO Base/Limit */
+	pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
+
+	/* Prefetchable MMIO Base/Limit */
+	pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
+	pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
+	pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
+}
+#endif	/* CONFIG_PCI_QUIRKS */
+
 int pci_assign_resource(struct pci_dev *dev, int resno)
 {
 	struct pci_bus *bus = dev->bus;