LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* x86 mac testers needed
@ 2006-09-12  6:58 Andi Kleen
  2006-09-12 12:04 ` Tino Keitel
  0 siblings, 1 reply; 2+ messages in thread
From: Andi Kleen @ 2006-09-12  6:58 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 392 bytes --]


Hello,

We need someone with a x86 Mac that didn't boot with 2.6.18rc2 or earlier
without applying patches.  We got one report of this, but the original
reporter isn't answering anymore.

Can you please add the attached patches to 2.6.18rc6 and report
if your system boots now? 

Patch order is 

pci-probe-type1-first
i386-acpi-mcfg-check
acpi-mcfg-check
remove-mcfg-dmi

Thank you,

-Andi

[-- Attachment #2: acpi-mcfg-check --]
[-- Type: text/x-diff, Size: 1638 bytes --]

improve extended config space verification

From: rajesh.shah@intel.com

Extend the verification for PCI-X/PCI-Express extended config
space pointer. This patch checks whether the MCFG address range
is listed as a motherboard resource, per the PCI firmware spec.
The old check only looked in int 15 e820 memory map, causing
several systems to fail the verification and lose extended
config space. x86_64 picks up the verification code from the i386
directory.

[AK: Also changed by me to use new type1 heuristic and some cleanups]

Cc: gregkh@suse.de

Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>

 arch/x86_64/pci/mmconfig.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

Index: linux-2.6.18rc6-update/arch/x86_64/pci/mmconfig.c
===================================================================
--- linux-2.6.18rc6-update.orig/arch/x86_64/pci/mmconfig.c
+++ linux-2.6.18rc6-update/arch/x86_64/pci/mmconfig.c
@@ -185,6 +185,17 @@ void __init pci_mmcfg_init(int type)
 	    (pci_mmcfg_config[0].base_address == 0))
 		return;
 
+	/* When Type1 access is not available don't check because
+	   we really need MCFG then and it's hopefully ok*/
+	if (type == 1 && !is_acpi_reserved(pci_mmcfg_config[0].base_address,
+					   pci_mmcfg_config[0].base_address +
+					   MMCONFIG_APER_MIN)) {
+		printk(KERN_ERR
+		       "PCI: BIOS Bug: MCFG area at %x not reserved in ACPI\n",
+		       pci_mmcfg_config[0].base_address);
+		return;
+	}
+
 	/* RED-PEN i386 doesn't do _nocache right now */
 	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
 	if (pci_mmcfg_virt == NULL) {

[-- Attachment #3: i386-acpi-mcfg-check --]
[-- Type: text/x-diff, Size: 6513 bytes --]

i386: PCI improve extended config space verification

From: rajesh.shah@intel.com

Extend the verification for PCI-X/PCI-Express extended config
space pointer. This patch checks whether the MCFG address range
is listed as a motherboard resource, per the PCI firmware spec.
The old check only looked in int 15 e820 memory map, causing
several systems to fail the verification and lose extended
config space.

[AK: Originally from Rajesh but somewhat hacked up by me. 
It now has a new heuristic to not do this check if Type1 
access doesn't work. This will hopefully fix the x86 iMacs.
Also assorted cleanups.]

Cc: gregkh@suse.d

Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>

 arch/i386/pci/acpi.c       |  101 +++++++++++++++++++++++++++++++++++++++++++++
 arch/i386/pci/mmconfig.c   |   11 +++-
 drivers/acpi/motherboard.c |    3 -
 include/acpi/aclocal.h     |    4 +
 4 files changed, 113 insertions(+), 6 deletions(-)

Index: linux/arch/i386/pci/acpi.c
===================================================================
--- linux.orig/arch/i386/pci/acpi.c
+++ linux/arch/i386/pci/acpi.c
@@ -5,6 +5,107 @@
 #include <asm/numa.h>
 #include "pci.h"
 
+static int __init is_motherboard_resource(acpi_handle handle)
+{
+       acpi_status status;
+       struct acpi_device_info *info;
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       int i;
+
+       status = acpi_get_object_info(handle, &buffer);
+       if (ACPI_FAILURE(status))
+	       return 0;
+       info = buffer.pointer;
+       if ((info->valid & ACPI_VALID_HID) &&
+		       (!strcmp(ACPI_MB_HID1, info->hardware_id.value) ||
+			!strcmp(ACPI_MB_HID2, info->hardware_id.value))) {
+	       kfree(buffer.pointer);
+	       return 1;
+       }
+       if (info->valid & ACPI_VALID_CID) {
+	       for (i=0; i < info->compatibility_id.count; i++) {
+		       if (!strcmp(ACPI_MB_HID1,
+				info->compatibility_id.id[i].value) ||
+				!strcmp(ACPI_MB_HID2,
+					info->compatibility_id.id[i].value)) {
+                                        kfree(buffer.pointer);
+                                        return 1;
+			}
+		}
+	}
+	kfree(buffer.pointer);
+        return 0;
+}
+
+static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
+		void *data)
+{
+	struct resource *mcfg_res = data;
+	struct acpi_resource_address64 address;
+	acpi_status status;
+
+	if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+		struct acpi_resource_fixed_memory32 *fixmem32;
+
+		fixmem32 = &res->data.fixed_memory32;
+		if (!fixmem32)
+			return AE_OK;
+		if ((mcfg_res->start >= fixmem32->address) &&
+			(mcfg_res->end <= (fixmem32->address +
+					   fixmem32->address_length))) {
+			mcfg_res->flags = 1;
+			return AE_CTRL_TERMINATE;
+		}
+	}
+	if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
+			(res->type != ACPI_RESOURCE_TYPE_ADDRESS64))
+		return AE_OK;
+
+	status = acpi_resource_to_address64(res, &address);
+	if (ACPI_FAILURE(status) || (address.address_length <= 0) ||
+			(address.resource_type != ACPI_MEMORY_RANGE))
+		return AE_OK;
+
+	if ((mcfg_res->start >= address.minimum) &&
+			(mcfg_res->end <=
+			 (address.minimum +address.address_length))) {
+		mcfg_res->flags = 1;
+		return AE_CTRL_TERMINATE;
+	}
+	return AE_OK;
+}
+
+static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
+		void *context, void **rv)
+{
+	struct resource *mcfg_res = context;
+	acpi_status status = AE_OK;
+
+	/* Stop namespace scanning if we've already verified MMCONFIG */
+	if (mcfg_res->flags)
+		return AE_CTRL_TERMINATE;
+
+	if (is_motherboard_resource(handle)) {
+		status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				check_mcfg_resource, context);
+	}
+	return status;
+}
+
+int __init is_acpi_reserved(unsigned long start, unsigned long end)
+{
+	struct resource mcfg_res;
+
+	mcfg_res.start = start;
+	mcfg_res.end = end;
+	mcfg_res.flags = 0;
+
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+			ACPI_UINT32_MAX, find_mboard_resource,
+			(void *)&mcfg_res, NULL);
+	return mcfg_res.flags;
+}
+
 struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
 {
 	struct pci_bus *bus;
Index: linux/arch/i386/pci/mmconfig.c
===================================================================
--- linux.orig/arch/i386/pci/mmconfig.c
+++ linux/arch/i386/pci/mmconfig.c
@@ -221,6 +221,17 @@ void __init pci_mmcfg_init(int type)
 	    (pci_mmcfg_config[0].base_address == 0))
 		return;
 
+	/* When Type1 access is not available don't check because
+	   we really need MCFG then and it's hopefully ok*/
+	if (type == 1 && !is_acpi_reserved(pci_mmcfg_config[0].base_address,
+					   pci_mmcfg_config[0].base_address +
+					   MMCONFIG_APER_MIN)) {
+		printk(KERN_ERR
+		       "PCI: BIOS Bug: MCFG area at %x not reserved in ACPI\n",
+		       pci_mmcfg_config[0].base_address);
+		return;
+	}
+
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
 	raw_pci_ops = &pci_mmcfg;
 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
Index: linux/drivers/acpi/motherboard.c
===================================================================
--- linux.orig/drivers/acpi/motherboard.c
+++ linux/drivers/acpi/motherboard.c
@@ -32,9 +32,6 @@
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME("acpi_motherboard")
 
-/* Dell use PNP0C01 instead of PNP0C02 */
-#define ACPI_MB_HID1			"PNP0C01"
-#define ACPI_MB_HID2			"PNP0C02"
 /**
  * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
  * Doesn't care about the failure of 'request_region', since other may reserve
Index: linux/include/acpi/aclocal.h
===================================================================
--- linux.orig/include/acpi/aclocal.h
+++ linux/include/acpi/aclocal.h
@@ -696,6 +696,10 @@ struct acpi_parse_state {
 
 #define PCI_ROOT_HID_STRING             "PNP0A03"
 #define PCI_EXPRESS_ROOT_HID_STRING     "PNP0A08"
+/* Dell use PNP0C01 instead of PNP0C02 */
+#define ACPI_MB_HID1			"PNP0C01"
+#define ACPI_MB_HID2			"PNP0C02"
+
 
 struct acpi_bit_register_info {
 	u8 parent_register;
Index: linux/arch/i386/pci/pci.h
===================================================================
--- linux.orig/arch/i386/pci/pci.h
+++ linux/arch/i386/pci/pci.h
@@ -88,5 +88,5 @@ extern void pci_pcbios_init(void);
 extern void pci_mmcfg_init(int type);
 extern void pcibios_sort(void);
 
-extern int is_acpi_reserved(unsigned long start, unsigned long end)
+extern int is_acpi_reserved(unsigned long start, unsigned long end);
 

[-- Attachment #4: pci-probe-type1-first --]
[-- Type: text/x-diff, Size: 3668 bytes --]

i386/x86-64: PCI: split probing and initialization of type 1 config space access

First probe if type1/2 accesses work, but then only initialize them at the end.

This is useful for a later patch that needs this information inbetween.

Index: linux/arch/i386/pci/direct.c
===================================================================
--- linux.orig/arch/i386/pci/direct.c
+++ linux/arch/i386/pci/direct.c
@@ -254,7 +254,16 @@ static int __init pci_check_type2(void)
 	return works;
 }
 
-void __init pci_direct_init(void)
+void __init pci_direct_init(int type)
+{
+	printk(KERN_INFO "PCI: Using configuration type %d\n", type);
+	if (type == 1)
+		raw_pci_ops = &pci_direct_conf1;
+	else
+		raw_pci_ops = &pci_direct_conf2;
+}
+
+int __init pci_direct_probe(void)
 {
 	struct resource *region, *region2;
 
@@ -264,19 +273,16 @@ void __init pci_direct_init(void)
 	if (!region)
 		goto type2;
 
-	if (pci_check_type1()) {
-		printk(KERN_INFO "PCI: Using configuration type 1\n");
-		raw_pci_ops = &pci_direct_conf1;
-		return;
-	}
+	if (pci_check_type1())
+		return 1;
 	release_resource(region);
 
  type2:
 	if ((pci_probe & PCI_PROBE_CONF2) == 0)
-		return;
+		return 0;
 	region = request_region(0xCF8, 4, "PCI conf2");
 	if (!region)
-		return;
+		return 0;
 	region2 = request_region(0xC000, 0x1000, "PCI conf2");
 	if (!region2)
 		goto fail2;
@@ -284,10 +290,11 @@ void __init pci_direct_init(void)
 	if (pci_check_type2()) {
 		printk(KERN_INFO "PCI: Using configuration type 2\n");
 		raw_pci_ops = &pci_direct_conf2;
-		return;
+		return 2;
 	}
 
 	release_resource(region2);
  fail2:
 	release_resource(region);
+	return 0;
 }
Index: linux/arch/i386/pci/init.c
===================================================================
--- linux.orig/arch/i386/pci/init.c
+++ linux/arch/i386/pci/init.c
@@ -6,8 +6,12 @@
    in the right sequence from here. */
 static __init int pci_access_init(void)
 {
+#ifdef CONFIG_PCI_DIRECT
+	int type = pci_direct_probe();
+#endif	
+
 #ifdef CONFIG_PCI_MMCONFIG
-	pci_mmcfg_init();
+	pci_mmcfg_init(type);
 #endif
 	if (raw_pci_ops)
 		return 0;
@@ -21,7 +25,7 @@ static __init int pci_access_init(void)
 	 * fails.
 	 */
 #ifdef CONFIG_PCI_DIRECT
-	pci_direct_init();
+	pci_direct_init(type);
 #endif
 	return 0;
 }
Index: linux/arch/i386/pci/mmconfig.c
===================================================================
--- linux.orig/arch/i386/pci/mmconfig.c
+++ linux/arch/i386/pci/mmconfig.c
@@ -208,7 +208,7 @@ static struct dmi_system_id __initdata d
          {}
 };
 
-void __init pci_mmcfg_init(void)
+void __init pci_mmcfg_init(int type)
 {
 	dmi_check_system(dmi_bad_mcfg);
 
Index: linux/arch/i386/pci/pci.h
===================================================================
--- linux.orig/arch/i386/pci/pci.h
+++ linux/arch/i386/pci/pci.h
@@ -82,7 +82,11 @@ extern int pci_conf1_write(unsigned int 
 extern int pci_conf1_read(unsigned int seg, unsigned int bus,
 			  unsigned int devfn, int reg, int len, u32 *value);
 
-extern void pci_direct_init(void);
+extern int pci_direct_probe(void);
+extern void pci_direct_init(int type);
 extern void pci_pcbios_init(void);
-extern void pci_mmcfg_init(void);
+extern void pci_mmcfg_init(int type);
 extern void pcibios_sort(void);
+
+extern int is_acpi_reserved(unsigned long start, unsigned long end)
+
Index: linux/arch/x86_64/pci/mmconfig.c
===================================================================
--- linux.orig/arch/x86_64/pci/mmconfig.c
+++ linux/arch/x86_64/pci/mmconfig.c
@@ -184,7 +184,7 @@ static struct dmi_system_id __initdata d
          {}
 };
 
-void __init pci_mmcfg_init(void)
+void __init pci_mmcfg_init(int type)
 {
 	int i;
 

[-- Attachment #5: remove-mcfg-dmi --]
[-- Type: text/x-diff, Size: 1954 bytes --]

Remove DMI entry to disable MCFG

We got a different heuristic now that should hopefully work it even
without blacklisting systems. So remove the entry for now.

Index: linux-2.6.18rc6-update/arch/i386/pci/mmconfig.c
===================================================================
--- linux-2.6.18rc6-update.orig/arch/i386/pci/mmconfig.c
+++ linux-2.6.18rc6-update/arch/i386/pci/mmconfig.c
@@ -188,23 +188,16 @@ static __init void unreachable_devices(v
 	}
 }
 
+#if 0
 static int disable_mcfg(struct dmi_system_id *d)
 {
 	printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
 	pci_probe &= ~PCI_PROBE_MMCONF;
 	return 0;
 }
+#endif
 
 static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
-	/* Has broken MCFG table that makes the system hang when used */
-        {
-         .callback = disable_mcfg,
-         .ident = "Intel D3C5105 SDV",
-         .matches = {
-                     DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
-                     DMI_MATCH(DMI_BOARD_NAME, "D26928"),
-                     },
-         },
          {}
 };
 
Index: linux-2.6.18rc6-update/arch/x86_64/pci/mmconfig.c
===================================================================
--- linux-2.6.18rc6-update.orig/arch/x86_64/pci/mmconfig.c
+++ linux-2.6.18rc6-update/arch/x86_64/pci/mmconfig.c
@@ -165,23 +165,16 @@ static __init void unreachable_devices(v
 	}
 }
 
+#if 0
 static int disable_mcfg(struct dmi_system_id *d)
 {
 	printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
 	pci_probe &= ~PCI_PROBE_MMCONF;
 	return 0;
 }
+#endif
 
 static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
-	/* Has broken MCFG table that makes the system hang when used */
-        {
-         .callback = disable_mcfg,
-         .ident = "Intel D3C5105 SDV",
-         .matches = {
-                     DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
-                     DMI_MATCH(DMI_BOARD_NAME, "D26928"),
-                     },
-         },
          {}
 };
 

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: x86 mac testers needed
  2006-09-12  6:58 x86 mac testers needed Andi Kleen
@ 2006-09-12 12:04 ` Tino Keitel
  0 siblings, 0 replies; 2+ messages in thread
From: Tino Keitel @ 2006-09-12 12:04 UTC (permalink / raw)
  To: linux-kernel

On Tue, Sep 12, 2006 at 08:58:14 +0200, Andi Kleen wrote:
> 
> Hello,
> 
> We need someone with a x86 Mac that didn't boot with 2.6.18rc2 or earlier
> without applying patches.  We got one report of this, but the original
> reporter isn't answering anymore.
> 
> Can you please add the attached patches to 2.6.18rc6 and report
> if your system boots now? 

Hi,

is the broken boot related to the boot method, e.g. via EFI or DOS
bootblock?

Regards,
Tino


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2006-09-12 12:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-09-12  6:58 x86 mac testers needed Andi Kleen
2006-09-12 12:04 ` Tino Keitel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).