Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
cec1ea6b
Commit
cec1ea6b
authored
Feb 29, 2004
by
Len Brown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ACPI] Support for PCI MMCONFIG for PCI Express (Matt Wilcox)
parent
594473bf
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
184 additions
and
7 deletions
+184
-7
arch/i386/Kconfig
arch/i386/Kconfig
+16
-6
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/boot.c
+31
-0
arch/i386/pci/Makefile
arch/i386/pci/Makefile
+1
-0
arch/i386/pci/common.c
arch/i386/pci/common.c
+8
-1
arch/i386/pci/mmconfig.c
arch/i386/pci/mmconfig.c
+109
-0
arch/i386/pci/pci.h
arch/i386/pci/pci.h
+3
-0
drivers/acpi/tables.c
drivers/acpi/tables.c
+1
-0
include/asm-i386/fixmap.h
include/asm-i386/fixmap.h
+3
-0
include/linux/acpi.h
include/linux/acpi.h
+12
-0
No files found.
arch/i386/Kconfig
View file @
cec1ea6b
...
@@ -1030,12 +1030,16 @@ config PCI_GOBIOS
...
@@ -1030,12 +1030,16 @@ config PCI_GOBIOS
PCI-based systems don't have any BIOS at all. Linux can also try to
PCI-based systems don't have any BIOS at all. Linux can also try to
detect the PCI hardware directly without using the BIOS.
detect the PCI hardware directly without using the BIOS.
With this option, you can specify how Linux should detect the PCI
With this option, you can specify how Linux should detect the
devices. If you choose "BIOS", the BIOS will be used, if you choose
PCI devices. If you choose "BIOS", the BIOS will be used,
"Direct", the BIOS won't be used, and if you choose "Any", the
if you choose "Direct", the BIOS won't be used, and if you
kernel will try the direct access method and falls back to the BIOS
choose "MMConfig", then PCI Express MMCONFIG will be used.
if that doesn't work. If unsure, go with the default, which is
If you choose "Any", the kernel will try MMCONFIG, then the
"Any".
direct access method and falls back to the BIOS if that doesn't
work. If unsure, go with the default, which is "Any".
config PCI_GOMMCONFIG
bool "MMConfig"
config PCI_GODIRECT
config PCI_GODIRECT
bool "Direct"
bool "Direct"
...
@@ -1055,6 +1059,12 @@ config PCI_DIRECT
...
@@ -1055,6 +1059,12 @@ config PCI_DIRECT
depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
default y
default y
config PCI_MMCONFIG
bool
depends on PCI && (PCI_GOMMCONFIG || PCI_GOANY)
select ACPI_BOOT
default y
config PCI_USE_VECTOR
config PCI_USE_VECTOR
bool "Vector-based interrupt indexing"
bool "Vector-based interrupt indexing"
depends on X86_LOCAL_APIC && X86_IO_APIC
depends on X86_LOCAL_APIC && X86_IO_APIC
...
...
arch/i386/kernel/acpi/boot.c
View file @
cec1ea6b
...
@@ -104,6 +104,31 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
...
@@ -104,6 +104,31 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
}
}
#ifdef CONFIG_PCI_MMCONFIG
static
int
__init
acpi_parse_mcfg
(
unsigned
long
phys_addr
,
unsigned
long
size
)
{
struct
acpi_table_mcfg
*
mcfg
;
if
(
!
phys_addr
||
!
size
)
return
-
EINVAL
;
mcfg
=
(
struct
acpi_table_mcfg
*
)
__acpi_map_table
(
phys_addr
,
size
);
if
(
!
mcfg
)
{
printk
(
KERN_WARNING
PREFIX
"Unable to map MCFG
\n
"
);
return
-
ENODEV
;
}
if
(
mcfg
->
base_reserved
)
{
printk
(
KERN_ERR
PREFIX
"MMCONFIG not in low 4GB of memory
\n
"
);
return
-
ENODEV
;
}
pci_mmcfg_base_addr
=
mcfg
->
base_address
;
return
0
;
}
#endif
/* CONFIG_PCI_MMCONFIG */
#ifdef CONFIG_X86_LOCAL_APIC
#ifdef CONFIG_X86_LOCAL_APIC
static
int
__init
static
int
__init
acpi_parse_madt
(
acpi_parse_madt
(
...
@@ -598,6 +623,12 @@ acpi_boot_init (void)
...
@@ -598,6 +623,12 @@ acpi_boot_init (void)
(
void
)
acpi_table_parse
(
ACPI_HPET
,
acpi_parse_hpet
);
(
void
)
acpi_table_parse
(
ACPI_HPET
,
acpi_parse_hpet
);
#endif
#endif
#ifdef CONFIG_PCI_MMCONFIG
error
=
acpi_table_parse
(
ACPI_MCFG
,
acpi_parse_mcfg
);
if
(
error
)
printk
(
KERN_ERR
PREFIX
"Error %d parsing MCFG
\n
"
,
error
);
#endif
return
0
;
return
0
;
}
}
arch/i386/pci/Makefile
View file @
cec1ea6b
obj-y
:=
i386.o
obj-y
:=
i386.o
obj-$(CONFIG_PCI_BIOS)
+=
pcbios.o
obj-$(CONFIG_PCI_BIOS)
+=
pcbios.o
obj-$(CONFIG_PCI_MMCONFIG)
+=
mmconfig.o
obj-$(CONFIG_PCI_DIRECT)
+=
direct.o
obj-$(CONFIG_PCI_DIRECT)
+=
direct.o
pci-y
:=
fixup.o
pci-y
:=
fixup.o
...
...
arch/i386/pci/common.c
View file @
cec1ea6b
...
@@ -20,7 +20,8 @@
...
@@ -20,7 +20,8 @@
extern
void
pcibios_sort
(
void
);
extern
void
pcibios_sort
(
void
);
#endif
#endif
unsigned
int
pci_probe
=
PCI_PROBE_BIOS
|
PCI_PROBE_CONF1
|
PCI_PROBE_CONF2
;
unsigned
int
pci_probe
=
PCI_PROBE_BIOS
|
PCI_PROBE_CONF1
|
PCI_PROBE_CONF2
|
PCI_PROBE_MMCONF
;
int
pcibios_last_bus
=
-
1
;
int
pcibios_last_bus
=
-
1
;
struct
pci_bus
*
pci_root_bus
=
NULL
;
struct
pci_bus
*
pci_root_bus
=
NULL
;
...
@@ -197,6 +198,12 @@ char * __devinit pcibios_setup(char *str)
...
@@ -197,6 +198,12 @@ char * __devinit pcibios_setup(char *str)
pci_probe
=
PCI_PROBE_CONF2
|
PCI_NO_CHECKS
;
pci_probe
=
PCI_PROBE_CONF2
|
PCI_NO_CHECKS
;
return
NULL
;
return
NULL
;
}
}
#endif
#ifdef CONFIG_PCI_MMCONFIG
else
if
(
!
strcmp
(
str
,
"nommconf"
))
{
pci_probe
&=
~
PCI_PROBE_MMCONF
;
return
NULL
;
}
#endif
#endif
else
if
(
!
strcmp
(
str
,
"noacpi"
))
{
else
if
(
!
strcmp
(
str
,
"noacpi"
))
{
acpi_noirq_set
();
acpi_noirq_set
();
...
...
arch/i386/pci/mmconfig.c
0 → 100644
View file @
cec1ea6b
/*
* mmconfig.c - Low-level direct PCI config space access via MMCONFIG
*/
#include <linux/pci.h>
#include <linux/init.h>
#include "pci.h"
/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
u32
pci_mmcfg_base_addr
;
#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
/* The base address of the last MMCONFIG device accessed */
static
u32
mmcfg_last_accessed_device
;
/*
* Functions for accessing PCI configuration space with MMCONFIG accesses
*/
static
inline
void
pci_exp_set_dev_base
(
int
bus
,
int
devfn
)
{
u32
dev_base
=
pci_mmcfg_base_addr
|
(
bus
<<
20
)
|
(
devfn
<<
12
);
if
(
dev_base
!=
mmcfg_last_accessed_device
)
{
mmcfg_last_accessed_device
=
dev_base
;
set_fixmap
(
FIX_PCIE_MCFG
,
dev_base
);
}
}
static
int
pci_mmcfg_read
(
int
seg
,
int
bus
,
int
devfn
,
int
reg
,
int
len
,
u32
*
value
)
{
unsigned
long
flags
;
if
(
!
value
||
(
bus
>
255
)
||
(
devfn
>
255
)
||
(
reg
>
4095
))
return
-
EINVAL
;
spin_lock_irqsave
(
&
pci_config_lock
,
flags
);
pci_exp_set_dev_base
(
bus
,
devfn
);
switch
(
len
)
{
case
1
:
*
value
=
readb
(
mmcfg_virt_addr
+
reg
);
break
;
case
2
:
*
value
=
readw
(
mmcfg_virt_addr
+
reg
);
break
;
case
4
:
*
value
=
readl
(
mmcfg_virt_addr
+
reg
);
break
;
}
spin_unlock_irqrestore
(
&
pci_config_lock
,
flags
);
return
0
;
}
static
int
pci_mmcfg_write
(
int
seg
,
int
bus
,
int
devfn
,
int
reg
,
int
len
,
u32
value
)
{
unsigned
long
flags
;
if
((
bus
>
255
)
||
(
devfn
>
255
)
||
(
reg
>
4095
))
return
-
EINVAL
;
spin_lock_irqsave
(
&
pci_config_lock
,
flags
);
pci_exp_set_dev_base
(
bus
,
devfn
);
switch
(
len
)
{
case
1
:
writeb
(
value
,
mmcfg_virt_addr
+
reg
);
break
;
case
2
:
writew
(
value
,
mmcfg_virt_addr
+
reg
);
break
;
case
4
:
writel
(
value
,
mmcfg_virt_addr
+
reg
);
break
;
}
/* Dummy read to flush PCI write */
readl
(
mmcfg_virt_addr
);
spin_unlock_irqrestore
(
&
pci_config_lock
,
flags
);
return
0
;
}
static
struct
pci_raw_ops
pci_mmcfg
=
{
.
read
=
pci_mmcfg_read
,
.
write
=
pci_mmcfg_write
,
};
static
int
__init
pci_mmcfg_init
(
void
)
{
if
((
pci_probe
&
PCI_PROBE_MMCONF
)
==
0
)
goto
out
;
if
(
!
pci_mmcfg_base_addr
)
goto
out
;
printk
(
KERN_INFO
"PCI: Using MMCONFIG
\n
"
);
raw_pci_ops
=
&
pci_mmcfg
;
pci_probe
=
(
pci_probe
&
~
PCI_PROBE_MASK
)
|
PCI_PROBE_MMCONF
;
out:
return
0
;
}
arch_initcall
(
pci_mmcfg_init
);
arch/i386/pci/pci.h
View file @
cec1ea6b
...
@@ -15,6 +15,9 @@
...
@@ -15,6 +15,9 @@
#define PCI_PROBE_BIOS 0x0001
#define PCI_PROBE_BIOS 0x0001
#define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_MMCONF 0x0008
#define PCI_PROBE_MASK 0x000f
#define PCI_NO_SORT 0x0100
#define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200
#define PCI_BIOS_SORT 0x0200
#define PCI_NO_CHECKS 0x0400
#define PCI_NO_CHECKS 0x0400
...
...
drivers/acpi/tables.c
View file @
cec1ea6b
...
@@ -58,6 +58,7 @@ static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
...
@@ -58,6 +58,7 @@ static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
[
ACPI_SSDT
]
=
"SSDT"
,
[
ACPI_SSDT
]
=
"SSDT"
,
[
ACPI_SPMI
]
=
"SPMI"
,
[
ACPI_SPMI
]
=
"SPMI"
,
[
ACPI_HPET
]
=
"HPET"
,
[
ACPI_HPET
]
=
"HPET"
,
[
ACPI_MCFG
]
=
"MCFG"
,
};
};
static
char
*
mps_inti_flags_polarity
[]
=
{
"dfl"
,
"high"
,
"res"
,
"low"
};
static
char
*
mps_inti_flags_polarity
[]
=
{
"dfl"
,
"high"
,
"res"
,
"low"
};
...
...
include/asm-i386/fixmap.h
View file @
cec1ea6b
...
@@ -70,6 +70,9 @@ enum fixed_addresses {
...
@@ -70,6 +70,9 @@ enum fixed_addresses {
#ifdef CONFIG_ACPI_BOOT
#ifdef CONFIG_ACPI_BOOT
FIX_ACPI_BEGIN
,
FIX_ACPI_BEGIN
,
FIX_ACPI_END
=
FIX_ACPI_BEGIN
+
FIX_ACPI_PAGES
-
1
,
FIX_ACPI_END
=
FIX_ACPI_BEGIN
+
FIX_ACPI_PAGES
-
1
,
#endif
#ifdef CONFIG_PCI_MMCONFIG
FIX_PCIE_MCFG
,
#endif
#endif
__end_of_permanent_fixed_addresses
,
__end_of_permanent_fixed_addresses
,
/* temporary boot-time mappings, used before ioremap() is functional */
/* temporary boot-time mappings, used before ioremap() is functional */
...
...
include/linux/acpi.h
View file @
cec1ea6b
...
@@ -317,6 +317,15 @@ struct acpi_table_ecdt {
...
@@ -317,6 +317,15 @@ struct acpi_table_ecdt {
char
ec_id
[
0
];
char
ec_id
[
0
];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
/* PCI MMCONFIG */
struct
acpi_table_mcfg
{
struct
acpi_table_header
header
;
u8
reserved
[
8
];
u32
base_address
;
u32
base_reserved
;
}
__attribute__
((
packed
));
/* Table Handlers */
/* Table Handlers */
enum
acpi_table_id
{
enum
acpi_table_id
{
...
@@ -338,6 +347,7 @@ enum acpi_table_id {
...
@@ -338,6 +347,7 @@ enum acpi_table_id {
ACPI_SSDT
,
ACPI_SSDT
,
ACPI_SPMI
,
ACPI_SPMI
,
ACPI_HPET
,
ACPI_HPET
,
ACPI_MCFG
,
ACPI_TABLE_COUNT
ACPI_TABLE_COUNT
};
};
...
@@ -369,6 +379,8 @@ void acpi_numa_arch_fixup(void);
...
@@ -369,6 +379,8 @@ void acpi_numa_arch_fixup(void);
extern
int
acpi_mp_config
;
extern
int
acpi_mp_config
;
extern
u32
pci_mmcfg_base_addr
;
#else
/*!CONFIG_ACPI_BOOT*/
#else
/*!CONFIG_ACPI_BOOT*/
#define acpi_mp_config 0
#define acpi_mp_config 0
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment