~ubuntu-branches/ubuntu/saucy/biosdevname/saucy-proposed

« back to all changes in this revision

Viewing changes to src/pci.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2011-02-23 17:58:36 UTC
  • Revision ID: james.westby@ubuntu.com-20110223175836-4f0cbcno9zm0lmdu
Tags: upstream-0.3.7
ImportĀ upstreamĀ versionĀ 0.3.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (c) 2006-2010 Dell, Inc.
 
3
 *  by Matt Domsch <Matt_Domsch@dell.com>
 
4
 *  Licensed under the GNU General Public license, version 2.
 
5
 */
 
6
#ifdef HAVE_CONFIG_H
 
7
#include "config.h"
 
8
#endif
 
9
 
 
10
#include <stdio.h>
 
11
#include <stdlib.h>
 
12
#include <string.h>
 
13
#include <strings.h>
 
14
#include <limits.h>
 
15
#include <unistd.h>
 
16
#include <dirent.h>
 
17
#include <pci/pci.h>
 
18
#include "pci.h"
 
19
#include "sysfs.h"
 
20
#include "dmidecode/dmidecode.h"
 
21
#include "pirq.h"
 
22
 
 
23
static int read_pci_sysfs_path(char *buf, size_t bufsize, const struct pci_dev *pdev)
 
24
{
 
25
        char path[PATH_MAX];
 
26
        char pci_name[16];
 
27
        ssize_t size;
 
28
        unparse_pci_name(pci_name, sizeof(pci_name), pdev);
 
29
        snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s", pci_name);
 
30
        size = readlink(path, buf, bufsize);
 
31
        if (size == -1)
 
32
                return 1;
 
33
        return 0;
 
34
}
 
35
 
 
36
static int read_pci_sysfs_physfn(char *buf, size_t bufsize, const struct pci_dev *pdev)
 
37
{
 
38
        char path[PATH_MAX];
 
39
        char pci_name[16];
 
40
        ssize_t size;
 
41
        unparse_pci_name(pci_name, sizeof(pci_name), pdev);
 
42
        snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/physfn", pci_name);
 
43
        size = readlink(path, buf, bufsize);
 
44
        if (size == -1)
 
45
                return 1;
 
46
        return 0;
 
47
}
 
48
 
 
49
static int virtfn_filter(const struct dirent *dent)
 
50
{
 
51
        return (!strncmp(dent->d_name,"virtfn",6));
 
52
}
 
53
 
 
54
static int _read_virtfn_index(unsigned int *index, const char *path, const char *basename, const char *pci_name)
 
55
{
 
56
        char buf[PATH_MAX], *b;
 
57
        char fullpath[PATH_MAX];
 
58
        ssize_t size;
 
59
        unsigned int u=INT_MAX;
 
60
        int scanned, rc=1;
 
61
 
 
62
        snprintf(fullpath, sizeof(fullpath), "%s/%s", path, basename);
 
63
        size = readlink(fullpath, buf, sizeof(buf));
 
64
        if (size > 0) {
 
65
                /* form is ../0000:05:10.0 */
 
66
                b=buf+3; /* skip ../ */
 
67
                if (strlen(b) == strlen(pci_name) &&
 
68
                    !strncmp(b, pci_name, strlen(pci_name))) {
 
69
                        scanned = sscanf(basename, "virtfn%u", &u);
 
70
                        if (scanned == 1) {
 
71
                                rc = 0;
 
72
                                *index = u;
 
73
                        }
 
74
                }
 
75
        }
 
76
        return rc;
 
77
}
 
78
 
 
79
static int read_virtfn_index(unsigned int *index, const struct pci_dev *pdev)
 
80
{
 
81
        char pci_name[16];
 
82
        char path[PATH_MAX];
 
83
        char cpath[PATH_MAX];
 
84
        struct dirent **namelist;
 
85
        int n, rc=1;
 
86
 
 
87
        unparse_pci_name(pci_name, sizeof(pci_name), pdev);
 
88
        snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/physfn", pci_name);
 
89
        if (realpath(path, cpath) == NULL)
 
90
                return rc;
 
91
 
 
92
        n = scandir(cpath, &namelist, virtfn_filter, versionsort);
 
93
        if (n < 0)
 
94
                return rc;
 
95
        else {
 
96
                while (n--) {
 
97
                        if (rc)
 
98
                                rc = _read_virtfn_index(index, cpath, namelist[n]->d_name, pci_name);
 
99
                        free(namelist[n]);
 
100
                }
 
101
                free(namelist);
 
102
        }
 
103
 
 
104
        return rc;
 
105
}
 
106
 
 
107
static int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func)
 
108
{
 
109
        int err;
 
110
/* The domain part was added in 2.6 kernels.  Test for that first. */
 
111
        err = sscanf(s, "%x:%2x:%2x.%x", domain, bus, dev, func);
 
112
        if (err != 4) {
 
113
                err = sscanf(s, "%2x:%2x.%x", bus, dev, func);
 
114
                if (err != 3) {
 
115
                        return 1;
 
116
                }
 
117
        }
 
118
        return 0;
 
119
}
 
120
 
 
121
static struct pci_dev * find_pdev_by_pci_name(struct pci_access *pacc, const char *s)
 
122
{
 
123
        int domain=0, bus=0, device=0, func=0;
 
124
        if (parse_pci_name(s, &domain, &bus, &device, &func))
 
125
                return NULL;
 
126
        return pci_get_dev(pacc, domain, bus, device, func);
 
127
}
 
128
 
 
129
static struct pci_device *
 
130
find_physfn(struct libbiosdevname_state *state, struct pci_device *dev)
 
131
{
 
132
        int rc;
 
133
        char path[PATH_MAX];
 
134
        char *c;
 
135
        struct pci_dev *pdev;
 
136
        memset(path, 0, sizeof(path));
 
137
        rc = read_pci_sysfs_physfn(path, sizeof(path), dev->pci_dev);
 
138
        if (rc != 0)
 
139
                return NULL;
 
140
        /* we get back a string like
 
141
           ../0000:05:0.0
 
142
           where the last component is the parent device
 
143
        */
 
144
        /* find the last backslash */
 
145
        c = rindex(path, '/');
 
146
        c++;
 
147
        pdev = find_pdev_by_pci_name(state->pacc, c);
 
148
        dev = find_dev_by_pci(state, pdev);
 
149
        return dev;
 
150
}
 
151
 
 
152
static int is_same_pci(const struct pci_dev *a, const struct pci_dev *b)
 
153
{
 
154
        if (pci_domain_nr(a) == pci_domain_nr(b) &&
 
155
            a->bus == b->bus &&
 
156
            a->dev == b->dev &&
 
157
            a->func == b->func)
 
158
                return 1;
 
159
        return 0;
 
160
}
 
161
 
 
162
static void try_add_vf_to_pf(struct libbiosdevname_state *state, struct pci_device *vf)
 
163
{
 
164
        struct pci_device *pf;
 
165
        unsigned int index=0;
 
166
        int rc;
 
167
        pf = find_physfn(state, vf);
 
168
 
 
169
        if (!pf)
 
170
                return;
 
171
        list_add_tail(&vf->vfnode, &pf->vfs);
 
172
        rc = read_virtfn_index(&index, vf->pci_dev);
 
173
        if (!rc) {
 
174
                vf->vf_index = index;
 
175
                pf->is_sriov_physical_function = 1;
 
176
        }
 
177
        vf->pf = pf;
 
178
        vf->physical_slot = pf->physical_slot;
 
179
}
 
180
 
 
181
static struct pci_device *
 
182
find_parent(struct libbiosdevname_state *state, struct pci_device *dev)
 
183
{
 
184
        int rc;
 
185
        char path[PATH_MAX];
 
186
        char *c;
 
187
        struct pci_device *physfn;
 
188
        struct pci_dev *pdev;
 
189
        memset(path, 0, sizeof(path));
 
190
        /* if this device has a physfn pointer, then treat _that_ as the parent */
 
191
        physfn = find_physfn(state, dev);
 
192
        if (physfn) {
 
193
                dev->is_sriov_virtual_function=1;
 
194
                return physfn;
 
195
        }
 
196
 
 
197
        rc = read_pci_sysfs_path(path, sizeof(path), dev->pci_dev);
 
198
        if (rc != 0)
 
199
                return NULL;
 
200
        /* we get back a string like
 
201
           ../../../devices/pci0000:00/0000:00:09.0/0000:05:17.4
 
202
           where the last component is the device we asked for
 
203
        */
 
204
        /* find the last backslash */
 
205
        c = rindex(path, '/');
 
206
        *c = '\0';
 
207
        /* find the last backslash again */
 
208
        c = rindex(path, '/');
 
209
        c++;
 
210
        pdev = find_pdev_by_pci_name(state->pacc, c);
 
211
        if (pdev) {
 
212
                dev = find_dev_by_pci(state, pdev);
 
213
                return dev;
 
214
        }
 
215
        return NULL;
 
216
}
 
217
 
 
218
/*
 
219
 * Check our parents in case the device itself isn't listed
 
220
 * in the SMBIOS table.  This has a problem, as
 
221
 * our parent bridge on a card may not be included
 
222
 * in the SMBIOS table.  In that case, it falls back to "unknown".
 
223
 */
 
224
static inline int pci_dev_to_slot(struct libbiosdevname_state *state, struct pci_device *dev)
 
225
{
 
226
        return dev->physical_slot;
 
227
}
 
228
 
 
229
static inline int pirq_dev_to_slot(struct libbiosdevname_state *state, struct pci_device *dev)
 
230
{
 
231
        return pirq_pci_dev_to_slot(state->pirq_table, pci_domain_nr(dev->pci_dev), dev->pci_dev->bus, dev->pci_dev->dev);
 
232
}
 
233
 
 
234
static void dev_to_slot(struct libbiosdevname_state *state, struct pci_device *dev)
 
235
{
 
236
        struct pci_device *d = dev;
 
237
        int slot;
 
238
        do {
 
239
                slot = pci_dev_to_slot(state, d);
 
240
                if (slot == PHYSICAL_SLOT_UNKNOWN)
 
241
                        slot = pirq_dev_to_slot(state, d);
 
242
                if (slot == PHYSICAL_SLOT_UNKNOWN)
 
243
                        d = find_parent(state, d);
 
244
        } while (d && slot == PHYSICAL_SLOT_UNKNOWN);
 
245
 
 
246
        dev->physical_slot = slot;
 
247
}
 
248
 
 
249
static char *read_pci_sysfs_label(const struct pci_dev *pdev)
 
250
{
 
251
        char path[PATH_MAX];
 
252
        char pci_name[16];
 
253
        int rc;
 
254
        char *label = NULL;
 
255
 
 
256
        unparse_pci_name(pci_name, sizeof(pci_name), pdev);
 
257
        snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/label", pci_name);
 
258
        rc = sysfs_read_file(path, &label);
 
259
        if (rc == 0)
 
260
                return label;
 
261
        return NULL;
 
262
}
 
263
 
 
264
static int read_pci_sysfs_index(unsigned int *index, const struct pci_dev *pdev)
 
265
{
 
266
        char path[PATH_MAX];
 
267
        char pci_name[16];
 
268
        int rc;
 
269
        char *indexstr = NULL;
 
270
        unsigned int i;
 
271
        unparse_pci_name(pci_name, sizeof(pci_name), pdev);
 
272
        snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/index", pci_name);
 
273
        rc = sysfs_read_file(path, &indexstr);
 
274
        if (rc == 0) {
 
275
                rc = sscanf(indexstr, "%u", &i);
 
276
                if (rc == 1)  {
 
277
                        *index = i;
 
278
                        return 0;
 
279
                }
 
280
        }
 
281
        return 1;
 
282
}
 
283
 
 
284
static void fill_pci_dev_sysfs(struct pci_device *dev, struct pci_dev *p)
 
285
{
 
286
        int rc;
 
287
        unsigned int index = 0;
 
288
        char *label = NULL;
 
289
        char buf[PATH_MAX];
 
290
        unparse_pci_name(buf, sizeof(buf), p);
 
291
        rc = read_pci_sysfs_index(&index, p);
 
292
        if (!rc) {
 
293
                dev->sysfs_index = index;
 
294
                dev->uses_sysfs |= HAS_SYSFS_INDEX;
 
295
        }
 
296
        label = read_pci_sysfs_label(p);
 
297
        if (label) {
 
298
                dev->sysfs_label = label;
 
299
                dev->uses_sysfs |= HAS_SYSFS_LABEL;
 
300
        }
 
301
}
 
302
 
 
303
static void add_pci_dev(struct libbiosdevname_state *state,
 
304
                        struct pci_dev *p)
 
305
{
 
306
        struct pci_device *dev;
 
307
        dev = malloc(sizeof(*dev));
 
308
        if (!dev) {
 
309
                fprintf(stderr, "out of memory\n");
 
310
                return;
 
311
        }
 
312
        memset(dev, 0, sizeof(*dev));
 
313
        INIT_LIST_HEAD(&dev->node);
 
314
        INIT_LIST_HEAD(&dev->vfnode);
 
315
        INIT_LIST_HEAD(&dev->vfs);
 
316
        dev->pci_dev = p;
 
317
        dev->physical_slot = PHYSICAL_SLOT_UNKNOWN;
 
318
        dev->class         = pci_read_word(p, PCI_CLASS_DEVICE);
 
319
        dev->vf_index = INT_MAX;
 
320
        fill_pci_dev_sysfs(dev, p);
 
321
        list_add(&dev->node, &state->pci_devices);
 
322
}
 
323
 
 
324
void free_pci_devices(struct libbiosdevname_state *state)
 
325
{
 
326
        struct pci_device *pos, *next;
 
327
        list_for_each_entry_safe(pos, next, &state->pci_devices, node) {
 
328
                if (pos->smbios_label)
 
329
                        free(pos->smbios_label);
 
330
                if (pos->sysfs_label)
 
331
                        free(pos->sysfs_label);
 
332
                list_del(&pos->node);
 
333
                free(pos);
 
334
        }
 
335
}
 
336
 
 
337
static void set_pci_slots(struct libbiosdevname_state *state)
 
338
{
 
339
        struct pci_device *dev;
 
340
 
 
341
        list_for_each_entry(dev, &state->pci_devices, node) {
 
342
                dev_to_slot(state, dev);
 
343
        }
 
344
}
 
345
 
 
346
 
 
347
static int set_pci_slot_index(struct libbiosdevname_state *state)
 
348
{
 
349
        struct pci_device *pcidev;
 
350
        int prevslot=-1;
 
351
        int index=1;
 
352
 
 
353
        /* only iterate over the PCI devices, because the bios_device list may be incomplete due to renames happening in parallel */
 
354
        list_for_each_entry(pcidev, &state->pci_devices, node) {
 
355
                if (pcidev->physical_slot == 0) /* skip embedded devices */
 
356
                        continue;
 
357
                if (!is_pci_network(pcidev)) /* only look at PCI network devices */
 
358
                        continue;
 
359
                if (pcidev->is_sriov_virtual_function) /* skip sriov VFs, they're handled later */
 
360
                        continue;
 
361
                if (pcidev->physical_slot != prevslot) {
 
362
                        index=1;
 
363
                        prevslot = pcidev->physical_slot;
 
364
                }
 
365
                else
 
366
                        index++;
 
367
                pcidev->index_in_slot = index;
 
368
        }
 
369
        return 0;
 
370
}
 
371
 
 
372
static int set_embedded_index(struct libbiosdevname_state *state)
 
373
{
 
374
        struct pci_device *pcidev;
 
375
        int index=1;
 
376
 
 
377
        list_for_each_entry(pcidev, &state->pci_devices, node) {
 
378
                if (pcidev->physical_slot != 0) /* skip non-embedded devices */
 
379
                        continue;
 
380
                if (!is_pci_network(pcidev)) /* only look at PCI network devices */
 
381
                        continue;
 
382
                if (pcidev->is_sriov_virtual_function) /* skip sriov VFs, they're handled later */
 
383
                        continue;
 
384
                pcidev->embedded_index = index;
 
385
                pcidev->embedded_index_valid = 1;
 
386
                index++;
 
387
        }
 
388
        return 0;
 
389
}
 
390
 
 
391
static void set_sriov_pf_vf(struct libbiosdevname_state *state)
 
392
{
 
393
        struct pci_device *vf;
 
394
        list_for_each_entry(vf, &state->pci_devices, node) {
 
395
                if (!vf->is_sriov_virtual_function)
 
396
                        continue;
 
397
                try_add_vf_to_pf(state, vf);
 
398
        }
 
399
}
 
400
 
 
401
/*
 
402
 * This sorts the PCI devices by breadth-first domain/bus/dev/fn.
 
403
 */
 
404
static int sort_pci(const struct pci_device *a, const struct pci_device *b)
 
405
{
 
406
 
 
407
        if      (pci_domain_nr(a->pci_dev) < pci_domain_nr(b->pci_dev)) return -1;
 
408
        else if (pci_domain_nr(a->pci_dev) > pci_domain_nr(b->pci_dev)) return  1;
 
409
 
 
410
        if      (a->pci_dev->bus < b->pci_dev->bus) return -1;
 
411
        else if (a->pci_dev->bus > b->pci_dev->bus) return  1;
 
412
 
 
413
        if      (a->pci_dev->dev < b->pci_dev->dev) return -1;
 
414
        else if (a->pci_dev->dev > b->pci_dev->dev) return  1;
 
415
 
 
416
        if      (a->pci_dev->func < b->pci_dev->func) return -1;
 
417
        else if (a->pci_dev->func > b->pci_dev->func) return  1;
 
418
 
 
419
        return 0;
 
420
}
 
421
 
 
422
static void insertion_sort_devices(struct pci_device *a, struct list_head *list,
 
423
                                   int (*cmp)(const struct pci_device *, const struct pci_device *))
 
424
{
 
425
        struct pci_device *b;
 
426
        list_for_each_entry(b, list, node) {
 
427
                if (cmp(a, b) <= 0) {
 
428
                        list_move_tail(&a->node, &b->node);
 
429
                        return;
 
430
                }
 
431
        }
 
432
        list_move_tail(&a->node, list);
 
433
}
 
434
 
 
435
static void sort_device_list(struct libbiosdevname_state *state)
 
436
{
 
437
        LIST_HEAD(sorted_devices);
 
438
        struct pci_device *dev, *tmp;
 
439
        list_for_each_entry_safe(dev, tmp, &state->pci_devices, node) {
 
440
                insertion_sort_devices(dev, &sorted_devices, sort_pci);
 
441
        }
 
442
        list_splice(&sorted_devices, &state->pci_devices);
 
443
}
 
444
 
 
445
int get_pci_devices(struct libbiosdevname_state *state)
 
446
{
 
447
        struct pci_access *pacc;
 
448
        struct pci_dev *p;
 
449
        struct routing_table *table;
 
450
        int rc=0;
 
451
 
 
452
        table = pirq_alloc_read_table();
 
453
        if (table)
 
454
                state->pirq_table = table;
 
455
 
 
456
        pacc = pci_alloc();
 
457
        if (!pacc)
 
458
                return rc;
 
459
        state->pacc = pacc;
 
460
        pci_init(pacc);
 
461
        pci_scan_bus(pacc);
 
462
 
 
463
        for (p=pacc->devices; p; p=p->next) {
 
464
                add_pci_dev(state, p);
 
465
        }
 
466
        /* ordering here is important */
 
467
        dmidecode_main(state);  /* this will fail on Xen guests, that's OK */
 
468
        sort_device_list(state);
 
469
        set_pci_slots(state);
 
470
        set_embedded_index(state);
 
471
        set_pci_slot_index(state);
 
472
        set_sriov_pf_vf(state);
 
473
 
 
474
        return rc;
 
475
}
 
476
 
 
477
int unparse_pci_name(char *buf, int size, const struct pci_dev *pdev)
 
478
{
 
479
        return snprintf(buf, size, "%04x:%02x:%02x.%x",
 
480
                        pci_domain_nr(pdev), pdev->bus, pdev->dev, pdev->func);
 
481
}
 
482
 
 
483
static int unparse_location(char *buf, const int size, const int location)
 
484
{
 
485
        char *s = buf;
 
486
        if (location == 0)
 
487
                s += snprintf(s, size-(s-buf), "embedded");
 
488
        else if (location == INT_MAX)
 
489
                s += snprintf(s, size-(s-buf), "unknown");
 
490
        else if (location > 0)
 
491
                s += snprintf(s, size-(s-buf), "%u", location);
 
492
        else
 
493
                s += snprintf(s, size-(s-buf), "unknown");
 
494
        return (s-buf);
 
495
}
 
496
 
 
497
static int unparse_smbios_type41_type(char *buf, const int size, const int type)
 
498
{
 
499
        char *s = buf;
 
500
        const char *msg[] = {"Other",
 
501
                             "Unknown",
 
502
                             "Video",
 
503
                             "SCSI Controller",
 
504
                             "Ethernet",
 
505
                             "Token Ring",
 
506
                             "Sound",
 
507
                             "PATA Controller",
 
508
                             "SATA Controller",
 
509
                             "SAS Controller",
 
510
        };
 
511
        if (type > 0 && type <= sizeof(msg))
 
512
                s += snprintf(s, size-(s-buf), "%s\n", msg[type-1]);
 
513
        else
 
514
                s += snprintf(s, size-(s-buf), "<OUT OF SPEC>\n");
 
515
        return (s-buf);
 
516
}
 
517
 
 
518
int unparse_pci_device(char *buf, const int size, const struct pci_device *p)
 
519
{
 
520
        char *s = buf;
 
521
        struct pci_device *dev;
 
522
        char pci_name[16];
 
523
        s += snprintf(s, size-(s-buf), "PCI name      : ");
 
524
        s += unparse_pci_name(s,  size-(s-buf), p->pci_dev);
 
525
        s += snprintf(s, size-(s-buf), "\n");
 
526
        s += snprintf(s, size-(s-buf), "PCI Slot      : ");
 
527
        if (p->physical_slot < INT_MAX)
 
528
                s += unparse_location(s, size-(s-buf), p->physical_slot);
 
529
        else
 
530
                s += snprintf(s, size-(s-buf), "Unknown");
 
531
        s += snprintf(s, size-(s-buf), "\n");
 
532
        if (p->smbios_type) {
 
533
                s += snprintf(s, size-(s-buf), "SMBIOS Device Type: ");
 
534
                s += unparse_smbios_type41_type(s, size-(s-buf), p->smbios_type);
 
535
                s += snprintf(s, size-(s-buf), "SMBIOS Instance: %u\n", p->smbios_instance);
 
536
                s += snprintf(s, size-(s-buf), "SMBIOS Enabled: %s\n", p->smbios_instance?"True":"False");
 
537
        }
 
538
        if (p->uses_smbios & HAS_SMBIOS_LABEL && p->smbios_label)
 
539
                s += snprintf(s, size-(s-buf), "SMBIOS Label: %s\n", p->smbios_label);
 
540
        if (p->uses_sysfs & HAS_SYSFS_INDEX)
 
541
                s += snprintf(s, size-(s-buf), "sysfs Index: %u\n", p->sysfs_index);
 
542
        if (p->uses_sysfs & HAS_SYSFS_LABEL)
 
543
                s += snprintf(s, size-(s-buf), "sysfs Label: %s\n", p->sysfs_label);
 
544
        if (p->physical_slot > 0 && !p->is_sriov_virtual_function)
 
545
                s += snprintf(s, size-(s-buf), "Index in slot: %u\n", p->index_in_slot);
 
546
        if (p->embedded_index_valid)
 
547
                s += snprintf(s, size-(s-buf), "Embedded Index: %u\n", p->embedded_index);
 
548
 
 
549
        if (!list_empty(&p->vfs)) {
 
550
                s += snprintf(s, size-(s-buf), "Virtual Functions:\n");
 
551
                list_for_each_entry(dev, &p->vfs, vfnode) {
 
552
                        unparse_pci_name(pci_name, sizeof(pci_name), dev->pci_dev);
 
553
                        s += snprintf(s, size-(s-buf), "%s\n", pci_name);
 
554
                }
 
555
        }
 
556
 
 
557
        return (s-buf);
 
558
}
 
559
 
 
560
struct pci_device * find_dev_by_pci(const struct libbiosdevname_state *state,
 
561
                                    const struct pci_dev *p)
 
562
{
 
563
        struct pci_device *dev;
 
564
        list_for_each_entry(dev, &state->pci_devices, node) {
 
565
                if (is_same_pci(p, dev->pci_dev))
 
566
                        return dev;
 
567
        }
 
568
        return NULL;
 
569
}
 
570
 
 
571
struct pci_device * find_pci_dev_by_pci_addr(const struct libbiosdevname_state *state,
 
572
                                             const int domain, const int bus, const int device, const int func)
 
573
{
 
574
        struct pci_device *dev;
 
575
        struct pci_dev p;
 
576
        memset(&p, 0, sizeof(p));
 
577
 
 
578
#ifdef HAVE_STRUCT_PCI_DEV_DOMAIN
 
579
        p.domain = domain;
 
580
#endif
 
581
        p.bus = bus;
 
582
        p.dev = device;
 
583
        p.func = func;
 
584
 
 
585
        list_for_each_entry(dev, &state->pci_devices, node) {
 
586
                if (is_same_pci(&p, dev->pci_dev))
 
587
                        return dev;
 
588
        }
 
589
        return NULL;
 
590
}
 
591
 
 
592
struct pci_device * find_dev_by_pci_name(const struct libbiosdevname_state *state,
 
593
                                         const char *s)
 
594
{
 
595
        int domain=0, bus=0, device=0, func=0;
 
596
        if (parse_pci_name(s, &domain, &bus, &device, &func))
 
597
                return NULL;
 
598
 
 
599
        return find_pci_dev_by_pci_addr(state, domain, bus, device, func);
 
600
}