Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 15094
b: refs/heads/master
c: 928cf8c
h: refs/heads/master
v: v3
  • Loading branch information
Andi Kleen authored and Linus Torvalds committed Dec 13, 2005
1 parent 6aa806b commit 937f77f
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bf5421c309bb89e5106452bc840983b1b4754d61
refs/heads/master: 928cf8c62763349efc550a12f6518e52c3390906
4 changes: 2 additions & 2 deletions trunk/arch/i386/pci/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))

static int pci_conf1_read(unsigned int seg, unsigned int bus,
int pci_conf1_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
Expand Down Expand Up @@ -42,7 +42,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus,
return 0;
}

static int pci_conf1_write(unsigned int seg, unsigned int bus,
int pci_conf1_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
Expand Down
24 changes: 16 additions & 8 deletions trunk/arch/i386/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ static u32 get_base_addr(unsigned int seg, int bus)
while (1) {
++cfg_num;
if (cfg_num >= pci_mmcfg_config_num) {
/* something bad is going on, no cfg table is found. */
/* so we fall back to the old way we used to do this */
/* and just rely on the first entry to be correct. */
return pci_mmcfg_config[0].base_address;
/* Not found - fallback to type 1 */
return 0;
}
cfg = &pci_mmcfg_config[cfg_num];
if (cfg->pci_segment_group_number != seg)
Expand All @@ -44,9 +42,9 @@ static u32 get_base_addr(unsigned int seg, int bus)
}
}

static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn)
static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
{
u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12);
u32 dev_base = base | (bus << 20) | (devfn << 12);
if (dev_base != mmcfg_last_accessed_device) {
mmcfg_last_accessed_device = dev_base;
set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
Expand All @@ -57,13 +55,18 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
u32 base;

if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL;

base = get_base_addr(seg, bus);
if (!base)
return pci_conf1_read(seg,bus,devfn,reg,len,value);

spin_lock_irqsave(&pci_config_lock, flags);

pci_exp_set_dev_base(seg, bus, devfn);
pci_exp_set_dev_base(base, bus, devfn);

switch (len) {
case 1:
Expand All @@ -86,13 +89,18 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
u32 base;

if ((bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL;

base = get_base_addr(seg, bus);
if (!base)
return pci_conf1_write(seg,bus,devfn,reg,len,value);

spin_lock_irqsave(&pci_config_lock, flags);

pci_exp_set_dev_base(seg, bus, devfn);
pci_exp_set_dev_base(base, bus, devfn);

switch (len) {
case 1:
Expand Down
7 changes: 7 additions & 0 deletions trunk/arch/i386/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,10 @@ extern spinlock_t pci_config_lock;

extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev);

extern int pci_conf1_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value);
extern int pci_conf1_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value);


29 changes: 20 additions & 9 deletions trunk/arch/x86_64/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,17 @@ struct mmcfg_virt {
};
static struct mmcfg_virt *pci_mmcfg_virt;

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

while (1) {
++cfg_num;
if (cfg_num >= pci_mmcfg_config_num) {
/* something bad is going on, no cfg table is found. */
/* so we fall back to the old way we used to do this */
/* and just rely on the first entry to be correct. */
return pci_mmcfg_virt[0].virt;
/* Not found - fall back to type 1. This happens
e.g. on the internal devices of a K8 northbridge. */
return NULL;
}
cfg = pci_mmcfg_virt[cfg_num].cfg;
if (cfg->pci_segment_group_number != seg)
Expand All @@ -43,18 +42,25 @@ static char *get_virt(unsigned int seg, int bus)

static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{

return get_virt(seg, bus) + ((bus << 20) | (devfn << 12));
char *addr = get_virt(seg, bus);
if (!addr)
return NULL;
return addr + ((bus << 20) | (devfn << 12));
}

static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
char *addr = pci_dev_base(seg, bus, devfn);
char *addr;

/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
return -EINVAL;

addr = pci_dev_base(seg, bus, devfn);
if (!addr)
return pci_conf1_read(seg,bus,devfn,reg,len,value);

switch (len) {
case 1:
*value = readb(addr + reg);
Expand All @@ -73,11 +79,16 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
char *addr = pci_dev_base(seg, bus, devfn);
char *addr;

/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
return -EINVAL;

addr = pci_dev_base(seg, bus, devfn);
if (!addr)
return pci_conf1_write(seg,bus,devfn,reg,len,value);

switch (len) {
case 1:
writeb(value, addr + reg);
Expand Down

0 comments on commit 937f77f

Please sign in to comment.