PCI, x86: Add pci=pref_bar to realloc pref bars

So could reallocate 64bit pref mem above 4g.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 0126f10..600bd6f 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -35,6 +35,7 @@
 #define PCI_NOASSIGN_ROMS	0x80000
 #define PCI_ROOT_NO_CRS		0x100000
 #define PCI_NOASSIGN_BARS	0x200000
+#define PCI_ASSIGN_PREF_BARS	0x400000
 
 extern unsigned int pci_probe;
 extern unsigned long pirq_table_addr;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7e65128..852d1a7 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -576,6 +576,9 @@
 	} else if (!strcmp(str, "assign-busses")) {
 		pci_probe |= PCI_ASSIGN_ALL_BUSSES;
 		return NULL;
+	} else if (!strcmp(str, "pref_bar")) {
+		pci_probe |= PCI_ASSIGN_PREF_BARS;
+		return NULL;
 	} else if (!strcmp(str, "use_crs")) {
 		pci_probe |= PCI_USE__CRS;
 		return NULL;
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 6fbd5f2..301f712 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -209,7 +209,9 @@
 	for_each_pci_resource(dev, r, idx, PCI_BRIDGE_RES) {
 		if (!r->flags)
 			continue;
-		if (!r->start || pci_claim_resource(dev, idx) < 0) {
+		if (((r->flags & IORESOURCE_PREFETCH) &&
+		     (pci_probe & PCI_ASSIGN_PREF_BARS)) ||
+		    !r->start || pci_claim_resource(dev, idx) < 0) {
 			/*
 			 * Something is wrong with the region.
 			 * Invalidate the resource to prevent
@@ -250,15 +252,19 @@
 		else
 			disabled = !(command & PCI_COMMAND_MEMORY);
 		if (pass == disabled) {
+			if ((r->flags & IORESOURCE_PREFETCH) &&
+			    (pci_probe & PCI_ASSIGN_PREF_BARS))
+				goto clear_start;
 			dev_dbg(&dev->dev,
 				"BAR %d: reserving %pr (d=%d, p=%d)\n",
 				idx, r, disabled, pass);
-			if (pci_claim_resource(dev, idx) < 0) {
-				/* We'll assign a new address later */
-				pcibios_save_fw_addr(dev, idx, r->start);
-				r->end -= r->start;
-				r->start = 0;
-			}
+			if (!pci_claim_resource(dev, idx))
+				continue;
+clear_start:
+			/* We'll assign a new address later */
+			pcibios_save_fw_addr(dev, idx, r->start);
+			r->end -= r->start;
+			r->start = 0;
 		}
 	}
 	if (!pass) {