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
search.c
Go to the documentation of this file.
1
/*
2
* PCI searching functions.
3
*
4
* Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
5
* David Mosberger-Tang
6
* Copyright (C) 1997 -- 2000 Martin Mares <
[email protected]
>
7
* Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <
[email protected]
>
8
*/
9
10
#include <
linux/init.h
>
11
#include <linux/pci.h>
12
#include <linux/slab.h>
13
#include <linux/module.h>
14
#include <
linux/interrupt.h
>
15
#include "
pci.h
"
16
17
DECLARE_RWSEM
(pci_bus_sem);
18
EXPORT_SYMBOL_GPL
(pci_bus_sem);
19
20
/*
21
* find the upstream PCIe-to-PCI bridge of a PCI device
22
* if the device is PCIE, return NULL
23
* if the device isn't connected to a PCIe bridge (that is its parent is a
24
* legacy PCI bridge and the bridge is directly connected to bus 0), return its
25
* parent
26
*/
27
struct
pci_dev
*
28
pci_find_upstream_pcie_bridge
(
struct
pci_dev
*pdev)
29
{
30
struct
pci_dev
*
tmp
=
NULL
;
31
32
if
(pci_is_pcie(pdev))
33
return
NULL
;
34
while
(1) {
35
if
(pci_is_root_bus(pdev->
bus
))
36
break
;
37
pdev = pdev->
bus
->self;
38
/* a p2p bridge */
39
if
(!pci_is_pcie(pdev)) {
40
tmp = pdev;
41
continue
;
42
}
43
/* PCI device should connect to a PCIe bridge */
44
if
(pci_pcie_type(pdev) !=
PCI_EXP_TYPE_PCI_BRIDGE
) {
45
/* Busted hardware? */
46
WARN_ON_ONCE
(1);
47
return
NULL
;
48
}
49
return
pdev;
50
}
51
52
return
tmp
;
53
}
54
55
static
struct
pci_bus
*pci_do_find_bus(
struct
pci_bus
*
bus
,
unsigned
char
busnr)
56
{
57
struct
pci_bus
*
child
;
58
struct
list_head
*
tmp
;
59
60
if
(bus->
number
== busnr)
61
return
bus
;
62
63
list_for_each
(tmp, &bus->
children
) {
64
child = pci_do_find_bus(
pci_bus_b
(tmp), busnr);
65
if
(child)
66
return
child;
67
}
68
return
NULL
;
69
}
70
80
struct
pci_bus
*
pci_find_bus
(
int
domain,
int
busnr)
81
{
82
struct
pci_bus
*bus =
NULL
;
83
struct
pci_bus
*tmp_bus;
84
85
while
((bus =
pci_find_next_bus
(bus)) !=
NULL
) {
86
if
(
pci_domain_nr
(bus) != domain)
87
continue
;
88
tmp_bus = pci_do_find_bus(bus, busnr);
89
if
(tmp_bus)
90
return
tmp_bus;
91
}
92
return
NULL
;
93
}
94
104
struct
pci_bus
*
105
pci_find_next_bus
(
const
struct
pci_bus
*
from
)
106
{
107
struct
list_head
*
n
;
108
struct
pci_bus
*
b
=
NULL
;
109
110
WARN_ON
(
in_interrupt
());
111
down_read
(&
pci_bus_sem
);
112
n = from ? from->
node
.next : pci_root_buses.next;
113
if
(n != &pci_root_buses)
114
b =
pci_bus_b
(n);
115
up_read
(&
pci_bus_sem
);
116
return
b
;
117
}
118
133
struct
pci_dev
*
pci_get_slot
(
struct
pci_bus
*bus,
unsigned
int
devfn
)
134
{
135
struct
pci_dev
*
dev
;
136
137
WARN_ON
(
in_interrupt
());
138
down_read
(&
pci_bus_sem
);
139
140
list_for_each_entry
(dev, &bus->
devices
,
bus_list
) {
141
if
(dev->
devfn
== devfn)
142
goto
out
;
143
}
144
145
dev =
NULL
;
146
out
:
147
pci_dev_get
(dev);
148
up_read
(&
pci_bus_sem
);
149
return
dev
;
150
}
151
167
struct
pci_dev
*
pci_get_domain_bus_and_slot
(
int
domain,
unsigned
int
bus,
168
unsigned
int
devfn
)
169
{
170
struct
pci_dev
*
dev
=
NULL
;
171
172
for_each_pci_dev
(dev) {
173
if
(
pci_domain_nr
(dev->
bus
) == domain &&
174
(dev->
bus
->number == bus && dev->
devfn
== devfn))
175
return
dev
;
176
}
177
return
NULL
;
178
}
179
EXPORT_SYMBOL
(
pci_get_domain_bus_and_slot
);
180
181
static
int
match_pci_dev_by_id(
struct
device
*
dev
,
void
*
data
)
182
{
183
struct
pci_dev
*
pdev
=
to_pci_dev
(dev);
184
struct
pci_device_id
*
id
=
data
;
185
186
if
(pci_match_one_device(
id
, pdev))
187
return
1;
188
return
0;
189
}
190
191
/*
192
* pci_get_dev_by_id - begin or continue searching for a PCI device by id
193
* @id: pointer to struct pci_device_id to match for the device
194
* @from: Previous PCI device found in search, or %NULL for new search.
195
*
196
* Iterates through the list of known PCI devices. If a PCI device is found
197
* with a matching id a pointer to its device structure is returned, and the
198
* reference count to the device is incremented. Otherwise, %NULL is returned.
199
* A new search is initiated by passing %NULL as the @from argument. Otherwise
200
* if @from is not %NULL, searches continue from next device on the global
201
* list. The reference count for @from is always decremented if it is not
202
* %NULL.
203
*
204
* This is an internal function for use by the other search functions in
205
* this file.
206
*/
207
static
struct
pci_dev
*pci_get_dev_by_id(
const
struct
pci_device_id
*
id
,
208
struct
pci_dev
*
from
)
209
{
210
struct
device
*
dev
;
211
struct
device
*dev_start =
NULL
;
212
struct
pci_dev
*pdev =
NULL
;
213
214
WARN_ON
(
in_interrupt
());
215
if
(from)
216
dev_start = &from->
dev
;
217
dev =
bus_find_device
(&
pci_bus_type
, dev_start, (
void
*)
id
,
218
match_pci_dev_by_id);
219
if
(dev)
220
pdev =
to_pci_dev
(dev);
221
if
(from)
222
pci_dev_put
(from);
223
return
pdev;
224
}
225
242
struct
pci_dev
*
pci_get_subsys
(
unsigned
int
vendor
,
unsigned
int
device
,
243
unsigned
int
ss_vendor,
unsigned
int
ss_device,
244
struct
pci_dev
*from)
245
{
246
struct
pci_device_id
id = {
247
.
vendor
=
vendor
,
248
.device =
device
,
249
.subvendor = ss_vendor,
250
.subdevice = ss_device,
251
};
252
253
return
pci_get_dev_by_id(&
id
, from);
254
}
255
270
struct
pci_dev
*
271
pci_get_device
(
unsigned
int
vendor
,
unsigned
int
device
,
struct
pci_dev
*from)
272
{
273
return
pci_get_subsys
(vendor, device,
PCI_ANY_ID
,
PCI_ANY_ID
, from);
274
}
275
290
struct
pci_dev
*
pci_get_class
(
unsigned
int
class
,
struct
pci_dev
*from)
291
{
292
struct
pci_device_id
id = {
293
.
vendor
=
PCI_ANY_ID
,
294
.device =
PCI_ANY_ID
,
295
.subvendor =
PCI_ANY_ID
,
296
.subdevice =
PCI_ANY_ID
,
297
.class_mask =
PCI_ANY_ID
,
298
.class =
class
,
299
};
300
301
return
pci_get_dev_by_id(&
id
, from);
302
}
303
315
int
pci_dev_present
(
const
struct
pci_device_id
*ids)
316
{
317
struct
pci_dev
*found =
NULL
;
318
319
WARN_ON
(
in_interrupt
());
320
while
(ids->
vendor
|| ids->
subvendor
|| ids->
class_mask
) {
321
found = pci_get_dev_by_id(ids,
NULL
);
322
if
(found)
323
goto
exit
;
324
ids++;
325
}
326
exit
:
327
if
(found)
328
return
1;
329
return
0;
330
}
331
EXPORT_SYMBOL
(
pci_dev_present
);
332
333
/* For boot time work */
334
EXPORT_SYMBOL
(
pci_find_bus
);
335
EXPORT_SYMBOL
(
pci_find_next_bus
);
336
/* For everyone */
337
EXPORT_SYMBOL
(
pci_get_device
);
338
EXPORT_SYMBOL
(
pci_get_subsys
);
339
EXPORT_SYMBOL
(
pci_get_slot
);
340
EXPORT_SYMBOL
(
pci_get_class
);
Generated on Thu Jan 10 2013 14:14:26 for Linux Kernel by
1.8.2