mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: rajesh.shah@intel.com
To: ak@suse.de, gregkh@suse.de
Cc: akpm@osdl.org, brice@myri.com, 76306.1226@compuserve.com,
	arjan@linux.intel.com, linux-pci@atrey.karlin.mff.cuni.cz,
	linux-kernel@vger.kernel.org, Rajesh Shah <rajesh.shah@intel.com>
Subject: [patch 1/2] i386 PCI: improve extended config space verification
Date: Fri, 23 Jun 2006 13:09:29 -0700	[thread overview]
Message-ID: <20060623201601.652662000@rshah1-sfield.jf.intel.com> (raw)
In-Reply-To: <20060623200928.036235000@rshah1-sfield.jf.intel.com>

[-- Attachment #1: i386-fix-mcfg-check --]
[-- Type: text/plain, Size: 5617 bytes --]

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.

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

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

Index: linux-2.6.17-mm1/arch/i386/pci/mmconfig.c
===================================================================
--- linux-2.6.17-mm1.orig/arch/i386/pci/mmconfig.c
+++ linux-2.6.17-mm1/arch/i386/pci/mmconfig.c
@@ -187,6 +187,108 @@ static __init void unreachable_devices(v
 	}
 }
 
+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;
+}
+
+
 void __init pci_mmcfg_init(void)
 {
 	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
@@ -201,10 +303,15 @@ void __init pci_mmcfg_init(void)
 	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
 			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
 			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
+		if (!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 is not reserved\n",
 				pci_mmcfg_config[0].base_address);
-		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-		return;
+			printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+			return;
+		}
 	}
 
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
Index: linux-2.6.17-mm1/include/acpi/aclocal.h
===================================================================
--- linux-2.6.17-mm1.orig/include/acpi/aclocal.h
+++ linux-2.6.17-mm1/include/acpi/aclocal.h
@@ -697,6 +697,8 @@ struct acpi_parse_state {
 
 #define PCI_ROOT_HID_STRING             "PNP0A03"
 #define PCI_EXPRESS_ROOT_HID_STRING     "PNP0A08"
+#define ACPI_MB_HID1			"PNP0C01"
+#define ACPI_MB_HID2			"PNP0C02"
 
 struct acpi_bit_register_info {
 	u8 parent_register;
Index: linux-2.6.17-mm1/drivers/acpi/motherboard.c
===================================================================
--- linux-2.6.17-mm1.orig/drivers/acpi/motherboard.c
+++ linux-2.6.17-mm1/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

--

  reply	other threads:[~2006-06-23 20:13 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-06-23 20:09 [patch 0/2] " rajesh.shah
2006-06-23 20:09 ` rajesh.shah [this message]
2006-06-23 20:09 ` [patch 2/2] x86_64 " rajesh.shah
2006-06-23 20:30   ` Andi Kleen
2006-06-23 22:43     ` Greg KH
2006-06-27  0:57       ` Rajesh Shah
2006-06-23 20:18 ` [patch 0/2] " Jeff Garzik
2006-06-27  0:45 [patch 0/2] PCI: improve extended config space verification - take #2 rajesh.shah
2006-06-27  0:45 ` [patch 1/2] i386 PCI: improve extended config space verification rajesh.shah

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060623201601.652662000@rshah1-sfield.jf.intel.com \
    --to=rajesh.shah@intel.com \
    --cc=76306.1226@compuserve.com \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=arjan@linux.intel.com \
    --cc=brice@myri.com \
    --cc=gregkh@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@atrey.karlin.mff.cuni.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®