-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
x86/PCI: read root resources from IOH on Intel
For intel systems with multi IOH, we should read peer root resources directly from PCI config space, and don't trust _CRS. Signed-off-by: Yinghai Lu <yinghai.lu@sun.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
- Loading branch information
Yinghai Lu
authored and
Jesse Barnes
committed
Nov 4, 2009
1 parent
91d3f9b
commit 99935a7
Showing
4 changed files
with
135 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#ifdef CONFIG_X86_64 | ||
|
||
/* | ||
* sub bus (transparent) will use entres from 3 to store extra from | ||
* root, so need to make sure we have enought slot there, Should we | ||
* increase PCI_BUS_NUM_RESOURCES? | ||
*/ | ||
#define RES_NUM 16 | ||
struct pci_root_info { | ||
char name[12]; | ||
unsigned int res_num; | ||
struct resource res[RES_NUM]; | ||
int bus_min; | ||
int bus_max; | ||
int node; | ||
int link; | ||
}; | ||
|
||
/* 4 at this time, it may become to 32 */ | ||
#define PCI_ROOT_NR 4 | ||
extern int pci_root_num; | ||
extern struct pci_root_info pci_root_info[PCI_ROOT_NR]; | ||
|
||
extern void update_res(struct pci_root_info *info, size_t start, | ||
size_t end, unsigned long flags, int merge); | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* to read io range from IOH pci conf, need to do it after mmconfig is there | ||
*/ | ||
|
||
#include <linux/delay.h> | ||
#include <linux/dmi.h> | ||
#include <linux/pci.h> | ||
#include <linux/init.h> | ||
#include <asm/pci_x86.h> | ||
|
||
#include "bus_numa.h" | ||
|
||
static inline void print_ioh_resources(struct pci_root_info *info) | ||
{ | ||
int res_num; | ||
int busnum; | ||
int i; | ||
|
||
printk(KERN_DEBUG "IOH bus: [%02x, %02x]\n", | ||
info->bus_min, info->bus_max); | ||
res_num = info->res_num; | ||
busnum = info->bus_min; | ||
for (i = 0; i < res_num; i++) { | ||
struct resource *res; | ||
|
||
res = &info->res[i]; | ||
printk(KERN_DEBUG "IOH bus: %02x index %x %s: [%llx, %llx]\n", | ||
busnum, i, | ||
(res->flags & IORESOURCE_IO) ? "io port" : | ||
"mmio", | ||
res->start, res->end); | ||
} | ||
} | ||
|
||
#define IOH_LIO 0x108 | ||
#define IOH_LMMIOL 0x10c | ||
#define IOH_LMMIOH 0x110 | ||
#define IOH_LMMIOH_BASEU 0x114 | ||
#define IOH_LMMIOH_LIMITU 0x118 | ||
#define IOH_LCFGBUS 0x11c | ||
|
||
static void __devinit pci_root_bus_res(struct pci_dev *dev) | ||
{ | ||
u16 word; | ||
u32 dword; | ||
struct pci_root_info *info; | ||
u16 io_base, io_end; | ||
u32 mmiol_base, mmiol_end; | ||
u64 mmioh_base, mmioh_end; | ||
int bus_base, bus_end; | ||
|
||
if (pci_root_num >= PCI_ROOT_NR) { | ||
printk(KERN_DEBUG "intel_bus.c: PCI_ROOT_NR is too small\n"); | ||
return; | ||
} | ||
|
||
info = &pci_root_info[pci_root_num]; | ||
pci_root_num++; | ||
|
||
pci_read_config_word(dev, IOH_LCFGBUS, &word); | ||
bus_base = (word & 0xff); | ||
bus_end = (word & 0xff00) >> 8; | ||
sprintf(info->name, "PCI Bus #%02x", bus_base); | ||
info->bus_min = bus_base; | ||
info->bus_max = bus_end; | ||
|
||
pci_read_config_word(dev, IOH_LIO, &word); | ||
io_base = (word & 0xf0) << (12 - 4); | ||
io_end = (word & 0xf000) | 0xfff; | ||
update_res(info, io_base, io_end, IORESOURCE_IO, 0); | ||
|
||
pci_read_config_dword(dev, IOH_LMMIOL, &dword); | ||
mmiol_base = (dword & 0xff00) << (24 - 8); | ||
mmiol_end = (dword & 0xff000000) | 0xffffff; | ||
update_res(info, mmiol_base, mmiol_end, IORESOURCE_MEM, 0); | ||
|
||
pci_read_config_dword(dev, IOH_LMMIOH, &dword); | ||
mmioh_base = ((u64)(dword & 0xfc00)) << (26 - 10); | ||
mmioh_end = ((u64)(dword & 0xfc000000) | 0x3ffffff); | ||
pci_read_config_dword(dev, IOH_LMMIOH_BASEU, &dword); | ||
mmioh_base |= ((u64)(dword & 0x7ffff)) << 32; | ||
pci_read_config_dword(dev, IOH_LMMIOH_LIMITU, &dword); | ||
mmioh_end |= ((u64)(dword & 0x7ffff)) << 32; | ||
update_res(info, mmioh_base, mmioh_end, IORESOURCE_MEM, 0); | ||
|
||
print_ioh_resources(info); | ||
} | ||
|
||
/* intel IOH */ | ||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, pci_root_bus_res); |