Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
pci
bus.c
Go to the documentation of this file.
1
/*
2
* drivers/pci/bus.c
3
*
4
* From setup-res.c, by:
5
* Dave Rusling (
[email protected]
)
6
* David Mosberger (
[email protected]
)
7
* David Miller (
[email protected]
)
8
* Ivan Kokshaysky (
[email protected]
)
9
*/
10
#include <linux/module.h>
11
#include <linux/kernel.h>
12
#include <linux/pci.h>
13
#include <linux/errno.h>
14
#include <
linux/ioport.h
>
15
#include <
linux/proc_fs.h
>
16
#include <
linux/init.h
>
17
#include <linux/slab.h>
18
19
#include "
pci.h
"
20
21
void
pci_add_resource_offset
(
struct
list_head
*
resources
,
struct
resource
*
res
,
22
resource_size_t
offset
)
23
{
24
struct
pci_host_bridge_window
*
window
;
25
26
window = kzalloc(
sizeof
(
struct
pci_host_bridge_window
),
GFP_KERNEL
);
27
if
(!window) {
28
printk
(
KERN_ERR
"PCI: can't add host bridge window %pR\n"
, res);
29
return
;
30
}
31
32
window->
res
=
res
;
33
window->
offset
=
offset
;
34
list_add_tail
(&window->
list
, resources);
35
}
36
EXPORT_SYMBOL
(
pci_add_resource_offset
);
37
38
void
pci_add_resource
(
struct
list_head
*
resources
,
struct
resource
*
res
)
39
{
40
pci_add_resource_offset
(resources, res, 0);
41
}
42
EXPORT_SYMBOL
(
pci_add_resource
);
43
44
void
pci_free_resource_list
(
struct
list_head
*
resources
)
45
{
46
struct
pci_host_bridge_window
*
window
, *
tmp
;
47
48
list_for_each_entry_safe
(window, tmp, resources,
list
) {
49
list_del
(&window->
list
);
50
kfree
(window);
51
}
52
}
53
EXPORT_SYMBOL
(
pci_free_resource_list
);
54
55
void
pci_bus_add_resource
(
struct
pci_bus
*
bus
,
struct
resource
*
res
,
56
unsigned
int
flags
)
57
{
58
struct
pci_bus_resource
*bus_res;
59
60
bus_res = kzalloc(
sizeof
(
struct
pci_bus_resource
),
GFP_KERNEL
);
61
if
(!bus_res) {
62
dev_err
(&bus->
dev
,
"can't add %pR resource\n"
, res);
63
return
;
64
}
65
66
bus_res->
res
=
res
;
67
bus_res->
flags
=
flags
;
68
list_add_tail
(&bus_res->
list
, &bus->
resources
);
69
}
70
71
struct
resource
*
pci_bus_resource_n
(
const
struct
pci_bus
*
bus
,
int
n
)
72
{
73
struct
pci_bus_resource
*bus_res;
74
75
if
(n <
PCI_BRIDGE_RESOURCE_NUM
)
76
return
bus->
resource
[
n
];
77
78
n -=
PCI_BRIDGE_RESOURCE_NUM
;
79
list_for_each_entry
(bus_res, &bus->
resources
,
list
) {
80
if
(n-- == 0)
81
return
bus_res->
res
;
82
}
83
return
NULL
;
84
}
85
EXPORT_SYMBOL_GPL
(
pci_bus_resource_n
);
86
87
void
pci_bus_remove_resources
(
struct
pci_bus
*
bus
)
88
{
89
int
i
;
90
struct
pci_bus_resource
*bus_res, *
tmp
;
91
92
for
(i = 0; i <
PCI_BRIDGE_RESOURCE_NUM
; i++)
93
bus->
resource
[i] =
NULL
;
94
95
list_for_each_entry_safe
(bus_res, tmp, &bus->
resources
,
list
) {
96
list_del
(&bus_res->
list
);
97
kfree
(bus_res);
98
}
99
}
100
116
int
117
pci_bus_alloc_resource
(
struct
pci_bus
*
bus
,
struct
resource
*
res
,
118
resource_size_t
size
,
resource_size_t
align
,
119
resource_size_t
min
,
unsigned
int
type_mask
,
120
resource_size_t
(*alignf)(
void
*,
121
const
struct
resource
*,
122
resource_size_t
,
123
resource_size_t
),
124
void
*alignf_data)
125
{
126
int
i
,
ret
= -
ENOMEM
;
127
struct
resource
*
r
;
128
resource_size_t
max
= -1;
129
130
type_mask |=
IORESOURCE_IO
|
IORESOURCE_MEM
;
131
132
/* don't allocate too high if the pref mem doesn't support 64bit*/
133
if
(!(res->
flags
&
IORESOURCE_MEM_64
))
134
max =
PCIBIOS_MAX_MEM_32
;
135
136
pci_bus_for_each_resource(bus, r, i) {
137
if
(!r)
138
continue
;
139
140
/* type_mask must match */
141
if
((res->
flags
^ r->
flags
) & type_mask)
142
continue
;
143
144
/* We cannot allocate a non-prefetching resource
145
from a pre-fetching area */
146
if
((r->
flags
&
IORESOURCE_PREFETCH
) &&
147
!(res->
flags
&
IORESOURCE_PREFETCH
))
148
continue
;
149
150
/* Ok, try it out.. */
151
ret =
allocate_resource
(r, res, size,
152
r->
start
? : min,
153
max, align,
154
alignf, alignf_data);
155
if
(ret == 0)
156
break
;
157
}
158
return
ret
;
159
}
160
168
int
pci_bus_add_device
(
struct
pci_dev
*
dev
)
169
{
170
int
retval
;
171
172
pci_fixup_device
(
pci_fixup_final
, dev);
173
retval =
device_add
(&dev->
dev
);
174
if
(retval)
175
return
retval
;
176
177
dev->
is_added
= 1;
178
pci_proc_attach_device
(dev);
179
pci_create_sysfs_dev_files
(dev);
180
return
0;
181
}
182
189
int
pci_bus_add_child
(
struct
pci_bus
*bus)
190
{
191
int
retval
;
192
193
if
(bus->
bridge
)
194
bus->
dev
.parent = bus->
bridge
;
195
196
retval =
device_register
(&bus->
dev
);
197
if
(retval)
198
return
retval
;
199
200
bus->
is_added
= 1;
201
202
/* Create legacy_io and legacy_mem files for this bus */
203
pci_create_legacy_files(bus);
204
205
return
retval
;
206
}
207
220
void
pci_bus_add_devices
(
const
struct
pci_bus
*bus)
221
{
222
struct
pci_dev
*
dev
;
223
struct
pci_bus
*
child
;
224
int
retval
;
225
226
list_for_each_entry
(dev, &bus->
devices
, bus_list) {
227
/* Skip already-added devices */
228
if
(dev->
is_added
)
229
continue
;
230
retval =
pci_bus_add_device
(dev);
231
if
(retval)
232
dev_err
(&dev->
dev
,
"Error adding device, continuing\n"
);
233
}
234
235
list_for_each_entry
(dev, &bus->
devices
, bus_list) {
236
BUG_ON
(!dev->
is_added
);
237
238
child = dev->
subordinate
;
239
/*
240
* If there is an unattached subordinate bus, attach
241
* it and then scan for unattached PCI devices.
242
*/
243
if
(!child)
244
continue
;
245
if
(list_empty(&child->
node
)) {
246
down_write
(&
pci_bus_sem
);
247
list_add_tail
(&child->
node
, &dev->
bus
->children);
248
up_write
(&
pci_bus_sem
);
249
}
250
pci_bus_add_devices
(child);
251
252
/*
253
* register the bus with sysfs as the parent is now
254
* properly registered.
255
*/
256
if
(child->
is_added
)
257
continue
;
258
retval =
pci_bus_add_child
(child);
259
if
(retval)
260
dev_err
(&dev->
dev
,
"Error adding bus, continuing\n"
);
261
}
262
}
263
264
void
pci_enable_bridges
(
struct
pci_bus
*bus)
265
{
266
struct
pci_dev
*
dev
;
267
int
retval
;
268
269
list_for_each_entry
(dev, &bus->
devices
,
bus_list
) {
270
if
(dev->
subordinate
) {
271
if
(!pci_is_enabled(dev)) {
272
retval =
pci_enable_device
(dev);
273
if
(retval)
274
dev_err
(&dev->
dev
,
"Error enabling bridge (%d), continuing\n"
, retval);
275
pci_set_master
(dev);
276
}
277
pci_enable_bridges
(dev->
subordinate
);
278
}
279
}
280
}
281
295
void
pci_walk_bus
(
struct
pci_bus
*
top
,
int
(*
cb
)(
struct
pci_dev
*,
void
*),
296
void
*userdata)
297
{
298
struct
pci_dev
*
dev
;
299
struct
pci_bus
*
bus
;
300
struct
list_head
*
next
;
301
int
retval
;
302
303
bus =
top
;
304
down_read
(&
pci_bus_sem
);
305
next = top->
devices
.next;
306
for
(;;) {
307
if
(next == &bus->
devices
) {
308
/* end of this bus, go up or finish */
309
if
(bus == top)
310
break
;
311
next = bus->
self
->bus_list.next;
312
bus = bus->
self
->bus;
313
continue
;
314
}
315
dev =
list_entry
(next,
struct
pci_dev
, bus_list);
316
if
(dev->
subordinate
) {
317
/* this is a pci-pci bridge, do its devices next */
318
next = dev->
subordinate
->devices.next;
319
bus = dev->
subordinate
;
320
}
else
321
next = dev->
bus_list
.next;
322
323
retval =
cb
(dev, userdata);
324
if
(retval)
325
break
;
326
}
327
up_read
(&
pci_bus_sem
);
328
}
329
EXPORT_SYMBOL_GPL
(
pci_walk_bus
);
330
331
EXPORT_SYMBOL
(
pci_bus_alloc_resource
);
332
EXPORT_SYMBOL_GPL
(
pci_bus_add_device
);
333
EXPORT_SYMBOL
(
pci_bus_add_devices
);
334
EXPORT_SYMBOL
(
pci_enable_bridges
);
Generated on Thu Jan 10 2013 13:23:50 for Linux Kernel by
1.8.2