2007-01-09 18:59:17

by OGAWA Hirofumi

[permalink] [raw]
Subject: [PATCH 1/4] MMCONFIG: cleanup

This just cleans up.

Signed-off-by: OGAWA Hirofumi <[email protected]>
---

arch/i386/pci/mmconfig-shared.c | 50 +++++++++++++++++-----------------------
arch/i386/pci/mmconfig.c | 13 +++-------
arch/i386/pci/pci.h | 4 ++-
arch/x86_64/pci/mmconfig.c | 16 +++---------
4 files changed, 33 insertions(+), 50 deletions(-)

diff -puN arch/i386/pci/mmconfig-shared.c~pci-mmconfig-cleanup arch/i386/pci/mmconfig-shared.c
--- linux-2.6/arch/i386/pci/mmconfig-shared.c~pci-mmconfig-cleanup 2007-01-06 00:15:02.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/mmconfig-shared.c 2007-01-06 00:43:36.000000000 +0900
@@ -22,10 +22,6 @@
#define MMCONFIG_APER_MIN (2 * 1024*1024)
#define MMCONFIG_APER_MAX (256 * 1024*1024)

-/* Verify the first 16 busses. We assume that systems with more busses
- get MCFG right. */
-#define PCI_MMCFG_MAX_CHECK_BUS 16
-
DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);

/* K8 systems have some devices (typically in the builtin northbridge)
@@ -34,29 +30,30 @@ DECLARE_BITMAP(pci_mmcfg_fallback_slots,
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
and fallback for them. */
-static __init void unreachable_devices(void)
+static void __init unreachable_devices(void)
{
- int i, k;
+ int i, bus;
/* Use the max bus number from ACPI here? */
- for (k = 0; k < PCI_MMCFG_MAX_CHECK_BUS; k++) {
+ for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
for (i = 0; i < 32; i++) {
+ unsigned int devfn = PCI_DEVFN(i, 0);
u32 val1, val2;

- pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
+ pci_conf1_read(0, bus, devfn, 0, 4, &val1);
if (val1 == 0xffffffff)
continue;

- raw_pci_ops->read(0, k, PCI_DEVFN(i, 0), 0, 4, &val2);
+ raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
if (val1 != val2) {
- set_bit(i + 32*k, pci_mmcfg_fallback_slots);
+ set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
printk(KERN_NOTICE "PCI: No mmconfig possible"
- " on device %02x:%02x\n", k, i);
+ " on device %02x:%02x\n", bus, i);
}
}
}
}

-static __init const char *pci_mmcfg_e7520(void)
+static const char __init *pci_mmcfg_e7520(void)
{
u32 win;
pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
@@ -71,7 +68,7 @@ static __init const char *pci_mmcfg_e752
return "Intel Corporation E7520 Memory Controller Hub";
}

-static __init const char *pci_mmcfg_intel_945(void)
+static const char __init *pci_mmcfg_intel_945(void)
{
u32 pciexbar, mask = 0, len = 0;

@@ -124,7 +121,7 @@ struct pci_mmcfg_hostbridge_probe {
const char *(*probe)(void);
};

-static __initdata struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] = {
+static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
};
@@ -144,22 +141,20 @@ static int __init pci_mmcfg_check_hostbr
pci_mmcfg_config = NULL;
name = NULL;

- for (i = 0; !name && i < sizeof(pci_mmcfg_probes) / sizeof(pci_mmcfg_probes[0]); i++)
- if ((pci_mmcfg_probes[i].vendor == PCI_ANY_ID || pci_mmcfg_probes[i].vendor == vendor) &&
- (pci_mmcfg_probes[i].device == PCI_ANY_ID || pci_mmcfg_probes[i].device == device))
+ for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+ if (pci_mmcfg_probes[i].vendor == vendor &&
+ pci_mmcfg_probes[i].device == device)
name = pci_mmcfg_probes[i].probe();
-
+ }
if (name) {
- if (pci_mmcfg_config_num)
- printk(KERN_INFO "PCI: Found %s with MMCONFIG support.\n", name);
- else
- printk(KERN_INFO "PCI: Found %s without MMCONFIG support.\n", name);
+ printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
+ name, pci_mmcfg_config_num ? "with" : "without");
}

return name != NULL;
}

-static __init void pci_mmcfg_insert_resources(void)
+static void __init pci_mmcfg_insert_resources(void)
{
#define PCI_MMCFG_RESOURCE_NAME_LEN 19
int i;
@@ -169,7 +164,6 @@ static __init void pci_mmcfg_insert_reso

res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
pci_mmcfg_config_num, GFP_KERNEL);
-
if (!res) {
printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
return;
@@ -177,12 +171,12 @@ static __init void pci_mmcfg_insert_reso

names = (void *)&res[pci_mmcfg_config_num];
for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
- num_buses = pci_mmcfg_config[i].end_bus_number -
- pci_mmcfg_config[i].start_bus_number + 1;
+ struct acpi_table_mcfg_config *cfg = &pci_mmcfg_config[i];
+ num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
res->name = names;
snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
- pci_mmcfg_config[i].pci_segment_group_number);
- res->start = pci_mmcfg_config[i].base_address;
+ cfg->pci_segment_group_number);
+ res->start = cfg->base_address;
res->end = res->start + (num_buses << 20) - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
insert_resource(&iomem_resource, res);
diff -puN arch/i386/pci/pci.h~pci-mmconfig-cleanup arch/i386/pci/pci.h
--- linux-2.6/arch/i386/pci/pci.h~pci-mmconfig-cleanup 2007-01-06 00:19:21.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/pci.h 2007-01-06 00:41:31.000000000 +0900
@@ -96,7 +96,9 @@ extern void pcibios_sort(void);

/* pci-mmconfig.c */

+/* Verify the first 16 busses. We assume that systems with more busses
+ get MCFG right. */
#define PCI_MMCFG_MAX_CHECK_BUS 16
extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);

-extern int pci_mmcfg_arch_init(void);
+extern int __init pci_mmcfg_arch_init(void);
diff -puN arch/i386/pci/mmconfig.c~pci-mmconfig-cleanup arch/i386/pci/mmconfig.c
--- linux-2.6/arch/i386/pci/mmconfig.c~pci-mmconfig-cleanup 2007-01-06 00:19:36.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/mmconfig.c 2007-01-06 00:35:12.000000000 +0900
@@ -27,22 +27,17 @@ static int mmcfg_last_accessed_cpu;
*/
static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
{
- int cfg_num = -1;
+ int cfg_num;
struct acpi_table_mcfg_config *cfg;

if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
return 0;

- while (1) {
- ++cfg_num;
- if (cfg_num >= pci_mmcfg_config_num) {
- break;
- }
+ for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
cfg = &pci_mmcfg_config[cfg_num];
- if (cfg->pci_segment_group_number != seg)
- continue;
- if ((cfg->start_bus_number <= bus) &&
+ if (cfg->pci_segment_group_number == seg &&
+ (cfg->start_bus_number <= bus) &&
(cfg->end_bus_number >= bus))
return cfg->base_address;
}
diff -puN arch/x86_64/pci/mmconfig.c~pci-mmconfig-cleanup arch/x86_64/pci/mmconfig.c
--- linux-2.6/arch/x86_64/pci/mmconfig.c~pci-mmconfig-cleanup 2007-01-06 00:20:42.000000000 +0900
+++ linux-2.6-hirofumi/arch/x86_64/pci/mmconfig.c 2007-01-06 00:35:12.000000000 +0900
@@ -13,10 +13,6 @@

#include "pci.h"

-/* Verify the first 16 busses. We assume that systems with more busses
- get MCFG right. */
-#define PCI_MMCFG_MAX_CHECK_BUS 16
-
/* Static virtual mapping of the MMCONFIG aperture */
struct mmcfg_virt {
struct acpi_table_mcfg_config *cfg;
@@ -26,17 +22,13 @@ static struct mmcfg_virt *pci_mmcfg_virt

static char __iomem *get_virt(unsigned int seg, unsigned bus)
{
- int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;
+ int cfg_num;

- while (1) {
- ++cfg_num;
- if (cfg_num >= pci_mmcfg_config_num)
- break;
+ for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
cfg = pci_mmcfg_virt[cfg_num].cfg;
- if (cfg->pci_segment_group_number != seg)
- continue;
- if ((cfg->start_bus_number <= bus) &&
+ if (cfg->pci_segment_group_number == seg &&
+ (cfg->start_bus_number <= bus) &&
(cfg->end_bus_number >= bus))
return pci_mmcfg_virt[cfg_num].virt;
}
_


2007-01-09 19:00:17

by OGAWA Hirofumi

[permalink] [raw]
Subject: [PATCH 2/4] MMCONFIG: Reject a broken MCFG tables on Asus etc

This rejects a broken MCFG tables on Asus etc.
Arjan and Andi suggest this.

Signed-off-by: OGAWA Hirofumi <[email protected]>
---

arch/i386/pci/mmconfig-shared.c | 24 +++++++++++++++++++++++-
arch/i386/pci/mmconfig.c | 9 ---------
arch/x86_64/pci/mmconfig.c | 9 ---------
3 files changed, 23 insertions(+), 19 deletions(-)

diff -puN arch/i386/pci/mmconfig-shared.c~pci-mmconfig-reject-mcfg_broken arch/i386/pci/mmconfig-shared.c
--- linux-2.6/arch/i386/pci/mmconfig-shared.c~pci-mmconfig-reject-mcfg_broken 2007-01-06 00:43:43.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/mmconfig-shared.c 2007-01-06 00:43:43.000000000 +0900
@@ -184,6 +184,26 @@ static void __init pci_mmcfg_insert_reso
}
}

+static void __init pci_mmcfg_reject_broken(void)
+{
+ struct acpi_table_mcfg_config *cfg = &pci_mmcfg_config[0];
+
+ /*
+ * Handle more broken MCFG tables on Asus etc.
+ * They only contain a single entry for bus 0-0.
+ */
+ if (pci_mmcfg_config_num == 1 &&
+ cfg->pci_segment_group_number == 0 &&
+ (cfg->start_bus_number | cfg->end_bus_number) == 0) {
+ kfree(pci_mmcfg_config);
+ pci_mmcfg_config = NULL;
+ pci_mmcfg_config_num = 0;
+
+ printk(KERN_ERR "PCI: start and end of bus number is 0. "
+ "Rejected as broken MCFG.");
+ }
+}
+
void __init pci_mmcfg_init(int type)
{
int known_bridge = 0;
@@ -194,8 +214,10 @@ void __init pci_mmcfg_init(int type)
if (type == 1 && pci_mmcfg_check_hostbridge())
known_bridge = 1;

- if (!known_bridge)
+ if (!known_bridge) {
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+ pci_mmcfg_reject_broken();
+ }

if ((pci_mmcfg_config_num == 0) ||
(pci_mmcfg_config == NULL) ||
diff -puN arch/i386/pci/mmconfig.c~pci-mmconfig-reject-mcfg_broken arch/i386/pci/mmconfig.c
--- linux-2.6/arch/i386/pci/mmconfig.c~pci-mmconfig-reject-mcfg_broken 2007-01-06 00:43:43.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/mmconfig.c 2007-01-06 00:43:43.000000000 +0900
@@ -42,15 +42,6 @@ static u32 get_base_addr(unsigned int se
return cfg->base_address;
}

- /* Handle more broken MCFG tables on Asus etc.
- They only contain a single entry for bus 0-0. Assume
- this applies to all busses. */
- cfg = &pci_mmcfg_config[0];
- if (pci_mmcfg_config_num == 1 &&
- cfg->pci_segment_group_number == 0 &&
- (cfg->start_bus_number | cfg->end_bus_number) == 0)
- return cfg->base_address;
-
/* Fall back to type 0 */
return 0;
}
diff -puN arch/x86_64/pci/mmconfig.c~pci-mmconfig-reject-mcfg_broken arch/x86_64/pci/mmconfig.c
--- linux-2.6/arch/x86_64/pci/mmconfig.c~pci-mmconfig-reject-mcfg_broken 2007-01-06 00:43:43.000000000 +0900
+++ linux-2.6-hirofumi/arch/x86_64/pci/mmconfig.c 2007-01-06 00:43:43.000000000 +0900
@@ -33,15 +33,6 @@ static char __iomem *get_virt(unsigned i
return pci_mmcfg_virt[cfg_num].virt;
}

- /* Handle more broken MCFG tables on Asus etc.
- They only contain a single entry for bus 0-0. Assume
- this applies to all busses. */
- cfg = &pci_mmcfg_config[0];
- if (pci_mmcfg_config_num == 1 &&
- cfg->pci_segment_group_number == 0 &&
- (cfg->start_bus_number | cfg->end_bus_number) == 0)
- return pci_mmcfg_virt[0].virt;
-
/* Fall back to type 0 */
return NULL;
}
_

2007-01-09 19:00:49

by OGAWA Hirofumi

[permalink] [raw]
Subject: [PATCH 3/4] MMCONFIG: fix unreachable_devices()

Currently, unreachable_devices() compares value of mmconfig and value
of conf1. But it doesn't check the device is reachable or not.

Signed-off-by: OGAWA Hirofumi <[email protected]>
---

arch/i386/pci/mmconfig-shared.c | 12 +++++++-----
arch/i386/pci/mmconfig.c | 6 ++++++
arch/i386/pci/pci.h | 2 ++
arch/x86_64/pci/mmconfig.c | 6 ++++++
4 files changed, 21 insertions(+), 5 deletions(-)

diff -puN arch/i386/pci/mmconfig-shared.c~pci-mmconfig-fix-unreachable_devices arch/i386/pci/mmconfig-shared.c
--- linux-2.6/arch/i386/pci/mmconfig-shared.c~pci-mmconfig-fix-unreachable_devices 2007-01-06 00:47:39.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/mmconfig-shared.c 2007-01-06 04:47:21.000000000 +0900
@@ -43,12 +43,14 @@ static void __init unreachable_devices(v
if (val1 == 0xffffffff)
continue;

- raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
- if (val1 != val2) {
- set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
- printk(KERN_NOTICE "PCI: No mmconfig possible"
- " on device %02x:%02x\n", bus, i);
+ if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
+ raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
+ if (val1 == val2)
+ continue;
}
+ set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
+ printk(KERN_NOTICE "PCI: No mmconfig possible on device"
+ " %02x:%02x\n", bus, i);
}
}
}
diff -puN arch/i386/pci/mmconfig.c~pci-mmconfig-fix-unreachable_devices arch/i386/pci/mmconfig.c
--- linux-2.6/arch/i386/pci/mmconfig.c~pci-mmconfig-fix-unreachable_devices 2007-01-06 00:47:39.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/mmconfig.c 2007-01-06 04:47:14.000000000 +0900
@@ -136,6 +136,12 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};

+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+ unsigned int devfn)
+{
+ return get_base_addr(seg, bus, devfn) != 0;
+}
+
int __init pci_mmcfg_arch_init(void)
{
printk(KERN_INFO "PCI: Using MMCONFIG\n");
diff -puN arch/x86_64/pci/mmconfig.c~pci-mmconfig-fix-unreachable_devices arch/x86_64/pci/mmconfig.c
--- linux-2.6/arch/x86_64/pci/mmconfig.c~pci-mmconfig-fix-unreachable_devices 2007-01-06 00:47:39.000000000 +0900
+++ linux-2.6-hirofumi/arch/x86_64/pci/mmconfig.c 2007-01-06 04:47:14.000000000 +0900
@@ -112,6 +112,12 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};

+int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+ unsigned int devfn)
+{
+ return pci_dev_base(seg, bus, devfn) != NULL;
+}
+
int __init pci_mmcfg_arch_init(void)
{
int i;
diff -puN arch/i386/pci/pci.h~pci-mmconfig-fix-unreachable_devices arch/i386/pci/pci.h
--- linux-2.6/arch/i386/pci/pci.h~pci-mmconfig-fix-unreachable_devices 2007-01-06 00:47:39.000000000 +0900
+++ linux-2.6-hirofumi/arch/i386/pci/pci.h 2007-01-06 00:47:39.000000000 +0900
@@ -101,4 +101,6 @@ extern void pcibios_sort(void);
#define PCI_MMCFG_MAX_CHECK_BUS 16
extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);

+extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
+ unsigned int devfn);
extern int __init pci_mmcfg_arch_init(void);
_

2007-01-09 19:01:19

by OGAWA Hirofumi

[permalink] [raw]
Subject: [PATCH 4/4] MMCONFIG: Fix x86_64 ioremap base_address

Current mmconfig has some problems of remapped range. The base
address always corresponds to bus number 0, but currently we are
assuming it corresponds to start bus number.

This patch fixes the above problems.

Signed-off-by: OGAWA Hirofumi <[email protected]>
---

arch/x86_64/pci/mmconfig.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)

diff -puN arch/x86_64/pci/mmconfig.c~pci-mmconfig-ioremap-range-fix-mm arch/x86_64/pci/mmconfig.c
--- linux-2.6/arch/x86_64/pci/mmconfig.c~pci-mmconfig-ioremap-range-fix-mm 2007-01-06 01:04:47.000000000 +0900
+++ linux-2.6-hirofumi/arch/x86_64/pci/mmconfig.c 2007-01-06 01:05:35.000000000 +0900
@@ -118,6 +118,20 @@ int __init pci_mmcfg_arch_reachable(unsi
return pci_dev_base(seg, bus, devfn) != NULL;
}

+static void __iomem * __init mcfg_ioremap(struct acpi_table_mcfg_config *cfg)
+{
+ void __iomem *addr;
+ u32 size;
+
+ size = (cfg->end_bus_number + 1) << 20;
+ addr = ioremap_nocache(cfg->base_address, size);
+ if (addr) {
+ printk(KERN_INFO "PCI: Using MMCONFIG at %x - %x\n",
+ cfg->base_address, cfg->base_address + size - 1);
+ }
+ return addr;
+}
+
int __init pci_mmcfg_arch_init(void)
{
int i;
@@ -128,19 +142,14 @@ int __init pci_mmcfg_arch_init(void)
}

for (i = 0; i < pci_mmcfg_config_num; ++i) {
- u32 size = (pci_mmcfg_config[0].end_bus_number - pci_mmcfg_config[0].start_bus_number + 1) << 20;
pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
- pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
- size);
+ pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
if (!pci_mmcfg_virt[i].virt) {
printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
"segment %d\n",
pci_mmcfg_config[i].pci_segment_group_number);
return 0;
}
- printk(KERN_INFO "PCI: Using MMCONFIG at %x-%x\n",
- pci_mmcfg_config[i].base_address,
- pci_mmcfg_config[i].base_address + size - 1);
}

raw_pci_ops = &pci_mmcfg;
_

2007-01-10 00:31:06

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH 1/4] MMCONFIG: cleanup

On Tuesday 09 January 2007 19:59, OGAWA Hirofumi wrote:
> This just cleans up.

The mmconfig code has completely changed in -mm/x86_64 soon. Can you resubmit against
that please?

-Andi

2007-01-10 00:41:30

by OGAWA Hirofumi

[permalink] [raw]
Subject: Re: [PATCH 1/4] MMCONFIG: cleanup

Andi Kleen <[email protected]> writes:

> On Tuesday 09 January 2007 19:59, OGAWA Hirofumi wrote:
>> This just cleans up.
>
> The mmconfig code has completely changed in -mm/x86_64 soon. Can you resubmit against
> that please?

No problem. I'll do for next -mm.
--
OGAWA Hirofumi <[email protected]>