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
29473ec2
Commit
29473ec2
authored
Apr 30, 2012
by
Bjorn Helgaas
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/yinghai-hostbridge-cleanup' into next
parents
977f857c
c57ca65a
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
304 additions
and
267 deletions
+304
-267
arch/x86/pci/acpi.c
arch/x86/pci/acpi.c
+71
-45
arch/x86/pci/amd_bus.c
arch/x86/pci/amd_bus.c
+27
-49
arch/x86/pci/broadcom_bus.c
arch/x86/pci/broadcom_bus.c
+4
-8
arch/x86/pci/bus_numa.c
arch/x86/pci/bus_numa.c
+47
-22
arch/x86/pci/bus_numa.h
arch/x86/pci/bus_numa.h
+10
-8
arch/x86/pci/common.c
arch/x86/pci/common.c
+4
-23
drivers/pci/Makefile
drivers/pci/Makefile
+1
-1
drivers/pci/host-bridge.c
drivers/pci/host-bridge.c
+96
-0
drivers/pci/probe.c
drivers/pci/probe.c
+36
-110
include/linux/pci.h
include/linux/pci.h
+8
-1
No files found.
arch/x86/pci/acpi.c
View file @
29473ec2
...
...
@@ -9,11 +9,11 @@
struct
pci_root_info
{
struct
acpi_device
*
bridge
;
char
*
name
;
char
name
[
16
]
;
unsigned
int
res_num
;
struct
resource
*
res
;
struct
list_head
*
resources
;
int
busnum
;
struct
pci_sysdata
sd
;
};
static
bool
pci_use_crs
=
true
;
...
...
@@ -287,7 +287,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
}
}
static
void
add_resources
(
struct
pci_root_info
*
info
)
static
void
add_resources
(
struct
pci_root_info
*
info
,
struct
list_head
*
resources
)
{
int
i
;
struct
resource
*
res
,
*
root
,
*
conflict
;
...
...
@@ -311,53 +312,74 @@ static void add_resources(struct pci_root_info *info)
"ignoring host bridge window %pR (conflicts with %s %pR)
\n
"
,
res
,
conflict
->
name
,
conflict
);
else
pci_add_resource
(
info
->
resources
,
res
);
pci_add_resource
(
resources
,
res
);
}
}
static
void
free_pci_root_info_res
(
struct
pci_root_info
*
info
)
{
kfree
(
info
->
res
);
info
->
res
=
NULL
;
info
->
res_num
=
0
;
}
static
void
__release_pci_root_info
(
struct
pci_root_info
*
info
)
{
int
i
;
struct
resource
*
res
;
for
(
i
=
0
;
i
<
info
->
res_num
;
i
++
)
{
res
=
&
info
->
res
[
i
];
if
(
!
res
->
parent
)
continue
;
if
(
!
(
res
->
flags
&
(
IORESOURCE_MEM
|
IORESOURCE_IO
)))
continue
;
release_resource
(
res
);
}
free_pci_root_info_res
(
info
);
kfree
(
info
);
}
static
void
release_pci_root_info
(
struct
pci_host_bridge
*
bridge
)
{
struct
pci_root_info
*
info
=
bridge
->
release_data
;
__release_pci_root_info
(
info
);
}
static
void
get_current_resources
(
struct
acpi_device
*
device
,
int
busnum
,
int
domain
,
struct
list_head
*
resources
)
probe_pci_root_info
(
struct
pci_root_info
*
info
,
struct
acpi_device
*
device
,
int
busnum
,
int
domain
)
{
struct
pci_root_info
info
;
size_t
size
;
info
.
bridge
=
device
;
info
.
res_num
=
0
;
info
.
resources
=
resources
;
info
->
bridge
=
device
;
info
->
res_num
=
0
;
acpi_walk_resources
(
device
->
handle
,
METHOD_NAME__CRS
,
count_resource
,
&
info
);
if
(
!
info
.
res_num
)
info
);
if
(
!
info
->
res_num
)
return
;
size
=
sizeof
(
*
info
.
res
)
*
info
.
res_num
;
info
.
res
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
info
.
res
)
size
=
sizeof
(
*
info
->
res
)
*
info
->
res_num
;
info
->
res_num
=
0
;
info
->
res
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
info
->
res
)
return
;
info
.
name
=
kasprintf
(
GFP_KERNEL
,
"PCI Bus %04x:%02x"
,
domain
,
busnum
);
if
(
!
info
.
name
)
goto
name_alloc_fail
;
sprintf
(
info
->
name
,
"PCI Bus %04x:%02x"
,
domain
,
busnum
);
info
.
res_num
=
0
;
acpi_walk_resources
(
device
->
handle
,
METHOD_NAME__CRS
,
setup_resource
,
&
info
);
if
(
pci_use_crs
)
{
add_resources
(
&
info
);
return
;
}
kfree
(
info
.
name
);
name_alloc_fail:
kfree
(
info
.
res
);
info
);
}
struct
pci_bus
*
__devinit
pci_acpi_scan_root
(
struct
acpi_pci_root
*
root
)
{
struct
acpi_device
*
device
=
root
->
device
;
struct
pci_root_info
*
info
=
NULL
;
int
domain
=
root
->
segment
;
int
busnum
=
root
->
secondary
.
start
;
LIST_HEAD
(
resources
);
...
...
@@ -389,17 +411,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
if
(
node
!=
-
1
&&
!
node_online
(
node
))
node
=
-
1
;
/* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
*/
sd
=
kzalloc
(
sizeof
(
*
sd
),
GFP_KERNEL
);
if
(
!
sd
)
{
info
=
kzalloc
(
sizeof
(
*
info
),
GFP_KERNEL
);
if
(
!
info
)
{
printk
(
KERN_WARNING
"pci_bus %04x:%02x: "
"ignored (out of memory)
\n
"
,
domain
,
busnum
);
return
NULL
;
}
sd
=
&
info
->
sd
;
sd
->
domain
=
domain
;
sd
->
node
=
node
;
/*
...
...
@@ -413,22 +432,32 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* be replaced by sd.
*/
memcpy
(
bus
->
sysdata
,
sd
,
sizeof
(
*
sd
));
kfree
(
sd
);
kfree
(
info
);
}
else
{
get_current_resources
(
device
,
busnum
,
domain
,
&
resources
);
probe_pci_root_info
(
info
,
device
,
busnum
,
domain
);
/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
if
(
!
pci_use_crs
)
if
(
pci_use_crs
)
add_resources
(
info
,
&
resources
);
else
{
free_pci_root_info_res
(
info
);
x86_pci_root_bus_resources
(
busnum
,
&
resources
);
}
bus
=
pci_create_root_bus
(
NULL
,
busnum
,
&
pci_root_ops
,
sd
,
&
resources
);
if
(
bus
)
if
(
bus
)
{
bus
->
subordinate
=
pci_scan_child_bus
(
bus
);
else
pci_set_host_bridge_release
(
to_pci_host_bridge
(
bus
->
bridge
),
release_pci_root_info
,
info
);
}
else
{
pci_free_resource_list
(
&
resources
);
__release_pci_root_info
(
info
);
}
}
/* After the PCI-E bus has been walked and all devices discovered,
...
...
@@ -445,9 +474,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
}
}
if
(
!
bus
)
kfree
(
sd
);
if
(
bus
&&
node
!=
-
1
)
{
#ifdef CONFIG_ACPI_NUMA
if
(
pxm
>=
0
)
...
...
arch/x86/pci/amd_bus.c
View file @
29473ec2
...
...
@@ -32,6 +32,18 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
#define RANGE_NUM 16
static
struct
pci_root_info
__init
*
find_pci_root_info
(
int
node
,
int
link
)
{
struct
pci_root_info
*
info
;
/* find the position */
list_for_each_entry
(
info
,
&
pci_root_infos
,
list
)
if
(
info
->
node
==
node
&&
info
->
link
==
link
)
return
info
;
return
NULL
;
}
/**
* early_fill_mp_bus_to_node()
* called before pcibios_scan_root and pci_scan_bus
...
...
@@ -50,7 +62,6 @@ static int __init early_fill_mp_bus_info(void)
int
def_link
;
struct
pci_root_info
*
info
;
u32
reg
;
struct
resource
*
res
;
u64
start
;
u64
end
;
struct
range
range
[
RANGE_NUM
];
...
...
@@ -86,7 +97,6 @@ static int __init early_fill_mp_bus_info(void)
if
(
!
found
)
return
0
;
pci_root_num
=
0
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
int
min_bus
;
int
max_bus
;
...
...
@@ -105,13 +115,8 @@ static int __init early_fill_mp_bus_info(void)
#endif
link
=
(
reg
>>
8
)
&
0x03
;
info
=
&
pci_root_info
[
pci_root_num
];
info
->
bus_min
=
min_bus
;
info
->
bus_max
=
max_bus
;
info
->
node
=
node
;
info
->
link
=
link
;
info
=
alloc_pci_root_info
(
min_bus
,
max_bus
,
node
,
link
);
sprintf
(
info
->
name
,
"PCI Bus #%02x"
,
min_bus
);
pci_root_num
++
;
}
/* get the default node and link for left over res */
...
...
@@ -134,16 +139,10 @@ static int __init early_fill_mp_bus_info(void)
link
=
(
reg
>>
4
)
&
0x03
;
end
=
(
reg
&
0xfff000
)
|
0xfff
;
/* find the position */
for
(
j
=
0
;
j
<
pci_root_num
;
j
++
)
{
info
=
&
pci_root_info
[
j
];
if
(
info
->
node
==
node
&&
info
->
link
==
link
)
break
;
}
if
(
j
==
pci_root_num
)
info
=
find_pci_root_info
(
node
,
link
);
if
(
!
info
)
continue
;
/* not found */
info
=
&
pci_root_info
[
j
];
printk
(
KERN_DEBUG
"node %d link %d: io port [%llx, %llx]
\n
"
,
node
,
link
,
start
,
end
);
...
...
@@ -155,13 +154,8 @@ static int __init early_fill_mp_bus_info(void)
}
/* add left over io port range to def node/link, [0, 0xffff] */
/* find the position */
for
(
j
=
0
;
j
<
pci_root_num
;
j
++
)
{
info
=
&
pci_root_info
[
j
];
if
(
info
->
node
==
def_node
&&
info
->
link
==
def_link
)
break
;
}
if
(
j
<
pci_root_num
)
{
info
=
&
pci_root_info
[
j
];
info
=
find_pci_root_info
(
def_node
,
def_link
);
if
(
info
)
{
for
(
i
=
0
;
i
<
RANGE_NUM
;
i
++
)
{
if
(
!
range
[
i
].
end
)
continue
;
...
...
@@ -214,16 +208,10 @@ static int __init early_fill_mp_bus_info(void)
end
<<=
8
;
end
|=
0xffff
;
/* find the position */
for
(
j
=
0
;
j
<
pci_root_num
;
j
++
)
{
info
=
&
pci_root_info
[
j
];
if
(
info
->
node
==
node
&&
info
->
link
==
link
)
break
;
}
if
(
j
==
pci_root_num
)
continue
;
/* not found */
info
=
find_pci_root_info
(
node
,
link
);
info
=
&
pci_root_info
[
j
];
if
(
!
info
)
continue
;
printk
(
KERN_DEBUG
"node %d link %d: mmio [%llx, %llx]"
,
node
,
link
,
start
,
end
);
...
...
@@ -291,14 +279,8 @@ static int __init early_fill_mp_bus_info(void)
* add left over mmio range to def node/link ?
* that is tricky, just record range in from start_min to 4G
*/
for
(
j
=
0
;
j
<
pci_root_num
;
j
++
)
{
info
=
&
pci_root_info
[
j
];
if
(
info
->
node
==
def_node
&&
info
->
link
==
def_link
)
break
;
}
if
(
j
<
pci_root_num
)
{
info
=
&
pci_root_info
[
j
];
info
=
find_pci_root_info
(
def_node
,
def_link
);
if
(
info
)
{
for
(
i
=
0
;
i
<
RANGE_NUM
;
i
++
)
{
if
(
!
range
[
i
].
end
)
continue
;
...
...
@@ -309,20 +291,16 @@ static int __init early_fill_mp_bus_info(void)
}
}
for
(
i
=
0
;
i
<
pci_root_num
;
i
++
)
{
int
res_num
;
list_for_each_entry
(
info
,
&
pci_root_infos
,
list
)
{
int
busnum
;
struct
pci_root_res
*
root_res
;
info
=
&
pci_root_info
[
i
];
res_num
=
info
->
res_num
;
busnum
=
info
->
bus_min
;
printk
(
KERN_DEBUG
"bus: [%02x, %02x] on node %x link %x
\n
"
,
info
->
bus_min
,
info
->
bus_max
,
info
->
node
,
info
->
link
);
for
(
j
=
0
;
j
<
res_num
;
j
++
)
{
res
=
&
info
->
res
[
j
];
printk
(
KERN_DEBUG
"bus: %02x index %x %pR
\n
"
,
busnum
,
j
,
res
);
}
list_for_each_entry
(
root_res
,
&
info
->
resources
,
list
)
printk
(
KERN_DEBUG
"bus: %02x %pR
\n
"
,
busnum
,
&
root_res
->
res
);
}
return
0
;
...
...
arch/x86/pci/broadcom_bus.c
View file @
29473ec2
...
...
@@ -22,19 +22,15 @@
static
void
__init
cnb20le_res
(
u8
bus
,
u8
slot
,
u8
func
)
{
struct
pci_root_info
*
info
;
struct
pci_root_res
*
root_res
;
struct
resource
res
;
u16
word1
,
word2
;
u8
fbus
,
lbus
;
int
i
;
info
=
&
pci_root_info
[
pci_root_num
];
pci_root_num
++
;
/* read the PCI bus numbers */
fbus
=
read_pci_config_byte
(
bus
,
slot
,
func
,
0x44
);
lbus
=
read_pci_config_byte
(
bus
,
slot
,
func
,
0x45
);
info
->
bus_min
=
fbus
;
info
->
bus_max
=
lbus
;
info
=
alloc_pci_root_info
(
fbus
,
lbus
,
0
,
0
);
/*
* Add the legacy IDE ports on bus 0
...
...
@@ -86,8 +82,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
res
.
flags
=
IORESOURCE_BUS
;
printk
(
KERN_INFO
"CNB20LE PCI Host Bridge (domain 0000 %pR)
\n
"
,
&
res
);
for
(
i
=
0
;
i
<
info
->
res_num
;
i
++
)
printk
(
KERN_INFO
"host bridge window %pR
\n
"
,
&
info
->
res
[
i
]
);
list_for_each_entry
(
root_res
,
&
info
->
resources
,
list
)
printk
(
KERN_INFO
"host bridge window %pR
\n
"
,
&
root_res
->
res
);
}
static
int
__init
broadcom_postcore_init
(
void
)
...
...
arch/x86/pci/bus_numa.c
View file @
29473ec2
...
...
@@ -4,35 +4,38 @@
#include "bus_numa.h"
int
pci_root_num
;
struct
pci_root_info
pci_root_info
[
PCI_ROOT_NR
];
LIST_HEAD
(
pci_root_infos
);
void
x86_pci_root_bus_resources
(
int
bus
,
struct
list_head
*
resource
s
)
static
struct
pci_root_info
*
x86_find_pci_root_info
(
int
bu
s
)
{
int
i
;
int
j
;
struct
pci_root_info
*
info
;
if
(
!
pci_root_num
)
goto
default_resources
;
if
(
list_empty
(
&
pci_root_infos
)
)
return
NULL
;
for
(
i
=
0
;
i
<
pci_root_num
;
i
++
)
{
if
(
pci_root_info
[
i
].
bus_min
==
bus
)
break
;
}
list_for_each_entry
(
info
,
&
pci_root_infos
,
list
)
if
(
info
->
bus_min
==
bus
)
return
info
;
return
NULL
;
}
if
(
i
==
pci_root_num
)
void
x86_pci_root_bus_resources
(
int
bus
,
struct
list_head
*
resources
)
{
struct
pci_root_info
*
info
=
x86_find_pci_root_info
(
bus
);
struct
pci_root_res
*
root_res
;
if
(
!
info
)
goto
default_resources
;
printk
(
KERN_DEBUG
"PCI: root bus %02x: hardware-probed resources
\n
"
,
bus
);
info
=
&
pci_root_info
[
i
];
for
(
j
=
0
;
j
<
info
->
res_num
;
j
++
)
{
list_for_each_entry
(
root_res
,
&
info
->
resources
,
list
)
{
struct
resource
*
res
;
struct
resource
*
root
;
res
=
&
info
->
res
[
j
]
;
res
=
&
root_res
->
res
;
pci_add_resource
(
resources
,
res
);
if
(
res
->
flags
&
IORESOURCE_IO
)
root
=
&
ioport_resource
;
...
...
@@ -53,11 +56,32 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
pci_add_resource
(
resources
,
&
iomem_resource
);
}
struct
pci_root_info
__init
*
alloc_pci_root_info
(
int
bus_min
,
int
bus_max
,
int
node
,
int
link
)
{
struct
pci_root_info
*
info
;
info
=
kzalloc
(
sizeof
(
*
info
),
GFP_KERNEL
);
if
(
!
info
)
return
info
;
INIT_LIST_HEAD
(
&
info
->
resources
);
info
->
bus_min
=
bus_min
;
info
->
bus_max
=
bus_max
;
info
->
node
=
node
;
info
->
link
=
link
;
list_add_tail
(
&
info
->
list
,
&
pci_root_infos
);
return
info
;
}
void
__devinit
update_res
(
struct
pci_root_info
*
info
,
resource_size_t
start
,
resource_size_t
end
,
unsigned
long
flags
,
int
merge
)
{
int
i
;
struct
resource
*
res
;
struct
pci_root_res
*
root_res
;
if
(
start
>
end
)
return
;
...
...
@@ -69,11 +93,11 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
goto
addit
;
/* try to merge it with old one */
for
(
i
=
0
;
i
<
info
->
res_num
;
i
++
)
{
list_for_each_entry
(
root_res
,
&
info
->
resources
,
list
)
{
resource_size_t
final_start
,
final_end
;
resource_size_t
common_start
,
common_end
;
res
=
&
info
->
res
[
i
]
;
res
=
&
root_res
->
res
;
if
(
res
->
flags
!=
flags
)
continue
;
...
...
@@ -93,14 +117,15 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
addit:
/* need to add that */
if
(
info
->
res_num
>=
RES_NUM
)
root_res
=
kzalloc
(
sizeof
(
*
root_res
),
GFP_KERNEL
);
if
(
!
root_res
)
return
;
res
=
&
info
->
res
[
info
->
res_num
]
;
res
=
&
root_res
->
res
;
res
->
name
=
info
->
name
;
res
->
flags
=
flags
;
res
->
start
=
start
;
res
->
end
=
end
;
res
->
child
=
NULL
;
info
->
res_num
++
;
list_add_tail
(
&
root_res
->
list
,
&
info
->
resources
)
;
}
arch/x86/pci/bus_numa.h
View file @
29473ec2
...
...
@@ -4,22 +4,24 @@
* sub bus (transparent) will use entres from 3 to store extra from
* root, so need to make sure we have enough slot there.
*/
#define RES_NUM 16
struct
pci_root_res
{
struct
list_head
list
;
struct
resource
res
;
};
struct
pci_root_info
{
struct
list_head
list
;
char
name
[
12
];
unsigned
int
res_num
;
struct
resource
res
[
RES_NUM
];
struct
list_head
resources
;
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
struct
list_head
pci_root_infos
;
struct
pci_root_info
*
alloc_pci_root_info
(
int
bus_min
,
int
bus_max
,
int
node
,
int
link
);
extern
void
update_res
(
struct
pci_root_info
*
info
,
resource_size_t
start
,
resource_size_t
end
,
unsigned
long
flags
,
int
merge
);
#endif
arch/x86/pci/common.c
View file @
29473ec2
...
...
@@ -430,9 +430,7 @@ void __init dmi_check_pciprobe(void)
struct
pci_bus
*
__devinit
pcibios_scan_root
(
int
busnum
)
{
LIST_HEAD
(
resources
);
struct
pci_bus
*
bus
=
NULL
;
struct
pci_sysdata
*
sd
;
while
((
bus
=
pci_find_next_bus
(
bus
))
!=
NULL
)
{
if
(
bus
->
number
==
busnum
)
{
...
...
@@ -441,28 +439,10 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
}
}
/* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
*/
sd
=
kzalloc
(
sizeof
(
*
sd
),
GFP_KERNEL
);
if
(
!
sd
)
{
printk
(
KERN_ERR
"PCI: OOM, not probing PCI bus %02x
\n
"
,
busnum
);
return
NULL
;
}
sd
->
node
=
get_mp_bus_to_node
(
busnum
);
printk
(
KERN_DEBUG
"PCI: Probing PCI hardware (bus %02x)
\n
"
,
busnum
);
x86_pci_root_bus_resources
(
busnum
,
&
resources
);
bus
=
pci_scan_root_bus
(
NULL
,
busnum
,
&
pci_root_ops
,
sd
,
&
resources
);
if
(
!
bus
)
{
pci_free_resource_list
(
&
resources
);
kfree
(
sd
);
}
return
bus
;
return
pci_scan_bus_on_node
(
busnum
,
&
pci_root_ops
,
get_mp_bus_to_node
(
busnum
));
}
void
__init
pcibios_set_cache_line_size
(
void
)
{
struct
cpuinfo_x86
*
c
=
&
boot_cpu_data
;
...
...
@@ -656,6 +636,7 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
}
sd
->
node
=
node
;
x86_pci_root_bus_resources
(
busno
,
&
resources
);
printk
(
KERN_DEBUG
"PCI: Probing PCI hardware (bus %02x)
\n
"
,
busno
);
bus
=
pci_scan_root_bus
(
NULL
,
busno
,
ops
,
sd
,
&
resources
);
if
(
!
bus
)
{
pci_free_resource_list
(
&
resources
);
...
...
drivers/pci/Makefile
View file @
29473ec2
...
...
@@ -2,7 +2,7 @@
# Makefile for the PCI bus specific drivers.
#
obj-y
+=
access.o bus.o probe.o remove.o pci.o
\
obj-y
+=
access.o bus.o probe.o
host-bridge.o
remove.o pci.o
\
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
\
irq.o vpd.o
obj-$(CONFIG_PROC_FS)
+=
proc.o
...
...
drivers/pci/host-bridge.c
0 → 100644
View file @
29473ec2
/*
* host bridge related code
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/module.h>
#include "pci.h"
static
struct
pci_bus
*
find_pci_root_bus
(
struct
pci_dev
*
dev
)
{
struct
pci_bus
*
bus
;
bus
=
dev
->
bus
;
while
(
bus
->
parent
)
bus
=
bus
->
parent
;
return
bus
;
}
static
struct
pci_host_bridge
*
find_pci_host_bridge
(
struct
pci_dev
*
dev
)
{
struct
pci_bus
*
bus
=
find_pci_root_bus
(
dev
);
return
to_pci_host_bridge
(
bus
->
bridge
);
}
void
pci_set_host_bridge_release
(
struct
pci_host_bridge
*
bridge
,
void
(
*
release_fn
)(
struct
pci_host_bridge
*
),
void
*
release_data
)
{
bridge
->
release_fn
=
release_fn
;
bridge
->
release_data
=
release_data
;
}
static
bool
resource_contains
(
struct
resource
*
res1
,
struct
resource
*
res2
)
{
return
res1
->
start
<=
res2
->
start
&&
res1
->
end
>=
res2
->
end
;
}
void
pcibios_resource_to_bus
(
struct
pci_dev
*
dev
,
struct
pci_bus_region
*
region
,
struct
resource
*
res
)
{
struct
pci_host_bridge
*
bridge
=
find_pci_host_bridge
(
dev
);
struct
pci_host_bridge_window
*
window
;
resource_size_t
offset
=
0
;
list_for_each_entry
(
window
,
&
bridge
->
windows
,
list
)
{
if
(
resource_type
(
res
)
!=
resource_type
(
window
->
res
))
continue
;
if
(
resource_contains
(
window
->
res
,
res
))
{
offset
=
window
->
offset
;
break
;
}
}
region
->
start
=
res
->
start
-
offset
;
region
->
end
=
res
->
end
-
offset
;
}
EXPORT_SYMBOL
(
pcibios_resource_to_bus
);
static
bool
region_contains
(
struct
pci_bus_region
*
region1
,
struct
pci_bus_region
*
region2
)
{
return
region1
->
start
<=
region2
->
start
&&
region1
->
end
>=
region2
->
end
;
}
void
pcibios_bus_to_resource
(
struct
pci_dev
*
dev
,
struct
resource
*
res
,
struct
pci_bus_region
*
region
)
{
struct
pci_host_bridge
*
bridge
=
find_pci_host_bridge
(
dev
);
struct
pci_host_bridge_window
*
window
;
resource_size_t
offset
=
0
;
list_for_each_entry
(
window
,
&
bridge
->
windows
,
list
)
{
struct
pci_bus_region
bus_region
;
if
(
resource_type
(
res
)
!=
resource_type
(
window
->
res
))
continue
;
bus_region
.
start
=
window
->
res
->
start
-
window
->
offset
;
bus_region
.
end
=
window
->
res
->
end
-
window
->
offset
;
if
(
region_contains
(
&
bus_region
,
region
))
{
offset
=
window
->
offset
;
break
;
}
}
res
->
start
=
region
->
start
+
offset
;
res
->
end
=
region
->
end
+
offset
;
}
EXPORT_SYMBOL
(
pcibios_bus_to_resource
);
drivers/pci/probe.c
View file @
29473ec2
...
...
@@ -15,13 +15,10 @@
#define CARDBUS_LATENCY_TIMER 176
/* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3
static
LIST_HEAD
(
pci_host_bridges
);
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD
(
pci_root_buses
);
EXPORT_SYMBOL
(
pci_root_buses
);
static
int
find_anything
(
struct
device
*
dev
,
void
*
data
)
{
return
1
;
...
...
@@ -44,82 +41,6 @@ int no_pci_devices(void)
}
EXPORT_SYMBOL
(
no_pci_devices
);
static
struct
pci_host_bridge
*
pci_host_bridge
(
struct
pci_dev
*
dev
)
{
struct
pci_bus
*
bus
;
struct
pci_host_bridge
*
bridge
;
bus
=
dev
->
bus
;
while
(
bus
->
parent
)
bus
=
bus
->
parent
;
list_for_each_entry
(
bridge
,
&
pci_host_bridges
,
list
)
{
if
(
bridge
->
bus
==
bus
)
return
bridge
;
}
return
NULL
;
}
static
bool
resource_contains
(
struct
resource
*
res1
,
struct
resource
*
res2
)
{
return
res1
->
start
<=
res2
->
start
&&
res1
->
end
>=
res2
->
end
;
}
void
pcibios_resource_to_bus
(
struct
pci_dev
*
dev
,
struct
pci_bus_region
*
region
,
struct
resource
*
res
)
{
struct
pci_host_bridge
*
bridge
=
pci_host_bridge
(
dev
);
struct
pci_host_bridge_window
*
window
;
resource_size_t
offset
=
0
;
list_for_each_entry
(
window
,
&
bridge
->
windows
,
list
)
{
if
(
resource_type
(
res
)
!=
resource_type
(
window
->
res
))
continue
;
if
(
resource_contains
(
window
->
res
,
res
))
{
offset
=
window
->
offset
;
break
;
}
}
region
->
start
=
res
->
start
-
offset
;
region
->
end
=
res
->
end
-
offset
;
}
EXPORT_SYMBOL
(
pcibios_resource_to_bus
);
static
bool
region_contains
(
struct
pci_bus_region
*
region1
,
struct
pci_bus_region
*
region2
)
{
return
region1
->
start
<=
region2
->
start
&&
region1
->
end
>=
region2
->
end
;
}
void
pcibios_bus_to_resource
(
struct
pci_dev
*
dev
,
struct
resource
*
res
,
struct
pci_bus_region
*
region
)
{
struct
pci_host_bridge
*
bridge
=
pci_host_bridge
(
dev
);
struct
pci_host_bridge_window
*
window
;
struct
pci_bus_region
bus_region
;
resource_size_t
offset
=
0
;
list_for_each_entry
(
window
,
&
bridge
->
windows
,
list
)
{
if
(
resource_type
(
res
)
!=
resource_type
(
window
->
res
))
continue
;
bus_region
.
start
=
window
->
res
->
start
-
window
->
offset
;
bus_region
.
end
=
window
->
res
->
end
-
window
->
offset
;
if
(
region_contains
(
&
bus_region
,
region
))
{
offset
=
window
->
offset
;
break
;
}
}
res
->
start
=
region
->
start
+
offset
;
res
->
end
=
region
->
end
+
offset
;
}
EXPORT_SYMBOL
(
pcibios_bus_to_resource
);
/*
* PCI Bus Class
*/
...
...
@@ -501,6 +422,19 @@ static struct pci_bus * pci_alloc_bus(void)
return
b
;
}
static
struct
pci_host_bridge
*
pci_alloc_host_bridge
(
struct
pci_bus
*
b
)
{
struct
pci_host_bridge
*
bridge
;
bridge
=
kzalloc
(
sizeof
(
*
bridge
),
GFP_KERNEL
);
if
(
bridge
)
{
INIT_LIST_HEAD
(
&
bridge
->
windows
);
bridge
->
bus
=
b
;
}
return
bridge
;
}
static
unsigned
char
pcix_bus_speed
[]
=
{
PCI_SPEED_UNKNOWN
,
/* 0 */
PCI_SPEED_66MHz_PCIX
,
/* 1 */
...
...
@@ -1201,7 +1135,14 @@ int pci_cfg_space_size(struct pci_dev *dev)
static
void
pci_release_bus_bridge_dev
(
struct
device
*
dev
)
{
kfree
(
dev
);
struct
pci_host_bridge
*
bridge
=
to_pci_host_bridge
(
dev
);
if
(
bridge
->
release_fn
)
bridge
->
release_fn
(
bridge
);
pci_free_resource_list
(
&
bridge
->
windows
);
kfree
(
bridge
);
}
struct
pci_dev
*
alloc_pci_dev
(
void
)
...
...
@@ -1650,28 +1591,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int
error
;
struct
pci_host_bridge
*
bridge
;
struct
pci_bus
*
b
,
*
b2
;
struct
device
*
dev
;
struct
pci_host_bridge_window
*
window
,
*
n
;
struct
resource
*
res
;
resource_size_t
offset
;
char
bus_addr
[
64
];
char
*
fmt
;
bridge
=
kzalloc
(
sizeof
(
*
bridge
),
GFP_KERNEL
);
if
(
!
bridge
)
return
NULL
;
b
=
pci_alloc_bus
();
if
(
!
b
)
goto
err_bus
;
dev
=
kzalloc
(
sizeof
(
*
dev
),
GFP_KERNEL
);
if
(
!
dev
)
goto
err_dev
;
return
NULL
;
b
->
sysdata
=
sysdata
;
b
->
ops
=
ops
;
b2
=
pci_find_bus
(
pci_domain_nr
(
b
),
bus
);
if
(
b2
)
{
/* If we already got to this bus through a different bridge, ignore it */
...
...
@@ -1679,13 +1611,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
goto
err_out
;
}
dev
->
parent
=
parent
;
dev
->
release
=
pci_release_bus_bridge_dev
;
dev_set_name
(
dev
,
"pci%04x:%02x"
,
pci_domain_nr
(
b
),
bus
);
error
=
device_register
(
dev
);
bridge
=
pci_alloc_host_bridge
(
b
);
if
(
!
bridge
)
goto
err_out
;
bridge
->
dev
.
parent
=
parent
;
bridge
->
dev
.
release
=
pci_release_bus_bridge_dev
;
dev_set_name
(
&
bridge
->
dev
,
"pci%04x:%02x"
,
pci_domain_nr
(
b
),
bus
);
error
=
device_register
(
&
bridge
->
dev
);
if
(
error
)
goto
dev_reg_err
;
b
->
bridge
=
get_device
(
dev
);
goto
bridge_
dev_reg_err
;
b
->
bridge
=
get_device
(
&
bridge
->
dev
);
device_enable_async_suspend
(
b
->
bridge
);
pci_set_bus_of_node
(
b
);
...
...
@@ -1704,9 +1640,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b
->
number
=
b
->
secondary
=
bus
;
bridge
->
bus
=
b
;
INIT_LIST_HEAD
(
&
bridge
->
windows
);
if
(
parent
)
dev_info
(
parent
,
"PCI host bridge to bus %s
\n
"
,
dev_name
(
&
b
->
dev
));
else
...
...
@@ -1732,25 +1665,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
}
down_write
(
&
pci_bus_sem
);
list_add_tail
(
&
bridge
->
list
,
&
pci_host_bridges
);
list_add_tail
(
&
b
->
node
,
&
pci_root_buses
);
up_write
(
&
pci_bus_sem
);
return
b
;
class_dev_reg_err:
device_unregister
(
dev
);
dev_reg_err:
down_write
(
&
pci_bus_sem
);
list_del
(
&
bridge
->
list
);
list_del
(
&
b
->
node
);
up_write
(
&
pci_bus_sem
);
put_device
(
&
bridge
->
dev
);
device_unregister
(
&
bridge
->
dev
);
bridge_dev_reg_err:
kfree
(
bridge
);
err_out:
kfree
(
dev
);
err_dev:
kfree
(
b
);
err_bus:
kfree
(
bridge
);
return
NULL
;
}
...
...
include/linux/pci.h
View file @
29473ec2
...
...
@@ -375,11 +375,18 @@ struct pci_host_bridge_window {
};
struct
pci_host_bridge
{
struct
list_head
list
;
struct
device
dev
;
struct
pci_bus
*
bus
;
/* root bus */
struct
list_head
windows
;
/* pci_host_bridge_windows */
void
(
*
release_fn
)(
struct
pci_host_bridge
*
);
void
*
release_data
;
};
#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
void
pci_set_host_bridge_release
(
struct
pci_host_bridge
*
bridge
,
void
(
*
release_fn
)(
struct
pci_host_bridge
*
),
void
*
release_data
);
/*
* The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
* to P2P or CardBus bridge windows) go in a table. Additional ones (for
...
...
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